In my app, for instance, when a user creates a new post, he or she can select a type of media (photo, video, text, place, etc.) and then review it in the following activity.
The way I have been doing it is to have all of the views (i.e. ImageView, VideoView, WebView, etc.) there, but set their visibility to invisible, unless the user chooses that type of media.
For instance, all of the views are invisible until the user takes a photo and then only the ImageView is visible. This seems wasteful though. Before I start the activity, I know which type of media the user chooses, but still have the invisible, unused views.
Would it be smarter to have separate layouts for each type of media with the repeated elements (the create post button, the privacy and venue buttons, etc.)? But this would violate the DRY principle...
How costly are invisible views? What is the correct way of doing this?
Depends on the complexity of the Layouts, I had this issue in previous app, in first iteration I did like you, but in 2nd iteration I found its hard to optimise single layout with bunch of invisible views; much less the if else cases to toggle views visibility.
and about layout performance, also it depends on layout/design complexity, I don't think unused view will consume that much of memory or cpu.
so if your layout is simple, its okay for now, if not I recommend to use separate layout for each design/type.
and as #ashishduh said, the best is to set visibility to GONE instead of INVISIBLE, since the parent layout will not measure GONE views, but this doesn't prevent view usage of memory or cpu (mostly in custom views)
Related
I have inherited a project where its user input screens are using single layout file. Depending on the type of user input required to show, a group of views are hidden or shown via View.GONE and View.VISIBLE. I don't understand why the old programmers did this. Is there a performance gain in this approach?
Official guideline about Improving Layout Performance
Sometimes your layout might require complex views that are rarely
used. Whether they are item details you can reduce memory usage and
speed up rendering by loading the views only when they are needed.
You can use ViewStub. It is zero sized invisible View that can be used to lazily inflate layout resource at runtime.
Sometimes might need to re-use larger components that require a special layout. To efficiently achieve this, You can try with Re-using Layouts with <include/>. Good way to share layout parts between different layout’s.
It could be a case of performance gain as Views will not be rendered. However, I am not certain why those developers went with this approach. If there are multiple views are not going to be used then rather create two separate layouts and based on the user, inflate one or the another.
In an Android application I'm building, I have a single activity which has multiple buttons and textviews. Based on user actions, I hide the elements and/or show them. This is intentional, cause I don't want the user to change activity.
For further clarity, the activity is a type controller. So when a user enables an option different buttons show up. This is why I want all of them in the same activity.
I am concerned about performance. Currently everything is in a Constraint Layout. Is there an effective way of having mutliple UI elements in the same activity, and having the ability to hide and show them at will? Should I look into Fragments?
Thank you in advance.
As it turns out there isn't a clear answer.
There are a few solutions that may prove useful, I list them below for anyone who might stumble onto this:
Fragment is useful when you have multiple independent parts of your layout. You are limited in the communication between elements of different Fragments.
ViewStub is used when you have some elements which are rarely used in your layout. This makes the initial loading of the layout lighter by not inflating the elements in the ViewStub. You can then inflate the elements on demand.
ViewFlipper allows you to cycle through a list of elements (or display them selectively using setDisplayedChild). It's mostly used for single elements, so I'm not sure about its performance if you were to use it for showing and hiding nested layouts.
ConstraintLayout is probably the best solution for cases similar to mine, where you have a layout of buttons and text which are hidden and displayed in a complex manner.
I'm making an app in which it might save me some time to
have a single layout for several activities, with some of the views set to GONE depending on which activity is being used.
I know that having a large number of views in a layout can lead to poor performance. If I had an activity with a large number of views, but a large portion of those views were to to GONE, would this activity still perform poorly. That is, do views that are set to GONE contribute to worsening performance? If yes, do they demand less processing power than VISIBLE or INVISIBLE views?
Thanks!
First thing you should know about gone vs invisible:
View.GONE This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE This view is invisible, but it still takes up space for layout purposes.
Thinking about the impact on measuring.
Which one is more efficient all depends on how frequently you are
changing the view's visibility.
For example, if the view is not visible for a majority of the time,
making it GONE would probably be more efficient, because the system
would not be needlessly measuring and laying out your invisible view
whenever it needs to adjust other views on the screen.
On the other hand, if the view changes between visible and invisible
frequently, you might get better performance from INVISIBLE as you
would potentially avoid an extra measure/layout on each transition.
Here is an interesting answer. I was wondering the same thing as you, and the answer is that View.GONE consumes more memory than simply calling removeView(view) on the view. However, GONE views do consume less memory than View.VISIBLE since they do not need to be drawn.
The memory amounts compare like this:
View.VISIBLE > View.GONE > removing the view from the container
What I do is use View.GONE on views that don't consume a lot of memory (like a TextView) and use parent.removeView(view) on views that are a lot of memory (like a WebView);
I typically organize my code/logic by a fragment represent one layout. Now I am in need of few relatively simple forms to get input data from user, which are somewhat related in purpose.
Say I hav 3 screens, and I could create 3 fragments to handle them (display view, read input, submit, ..). Or should I use one fragment, and use FrameLayout create a stack of layouts. I was thinking like, stacking all 3 views and hide/display the view I like. But the documentation say
Generally, FrameLayout should be used to hold a single child view,
because it can be difficult to organize child views in a way that's
scalable to different screen sizes without the children overlapping
each other
Any good way to do this or should I create multiple fragments for this (the down side of this is lot of small classes and repeated code. I may use a base class, still like to explore other options)
Thanks.
It sounds like you don't really care that much if the views overlap each other in the FrameLayout, or in fact they are supposed to overlap because you expect to be showing only one at a time. FrameLayout can certainly display stacked child views that each take up its full width and height just fine, and if you set the visibility of the unused views to INVISIBLE or GONE, they will not intercept screen presses or take focus if they happen to be located above the visible view the user is interacting with.
On the point of readability and code maintenance, I think swapping fragments makes more sense though, even if there is more memory overhead. The layout management can be encapsulated within the individual fragments, and you do not need to worry about showing/hiding views, as fragment transactions will take care of that aspect.
I have looked at this topic to dynamically add views when needed: Add and Remove Views in Android Dynamically?
However, I have a few questions.
1) Will there be a visible stutter or lag when creating these views on the go? For example, I use a panel system where each panel holds a separate view. However, these panels could reach a high number in quantity (40 odd panels?) when the program is complete. In order to preserve resources, I want only the view that is currently visible to actually be created, and the others views to not be instantiated until they are brought into the visible region. I have been told to use a ViewFlipper, but due to animation and user interaction requirements of my program, I cannot use a ViewFlipper, but have something along the same lines that I have created.
For example:
Imagine one of my "panels" to be pretty much like a screen in the Android Home launcher. The thing with the Home Launcher is that all it's views can be kept alive at any given time, because there's only really 7 of them. However, seeing as there are closer to 40 in mine (not all left and right, some above and below as well), I cannot have them all instantiated at the same time, or else the phone will begin to lag.
2) What is the code to destroy the views once they aren't in the visible region?
My program will determine when the panels are in the visible region or not, hence I will only need the code to destroy the views on the go.
Thanks.
Why don't you use a ListView or a GridView?
If you are not willing to use some of those, you will need to do something similar to what they do with the Adapter and how they recicle views.