I'm working in a project that requires to inflate a simple tutorial View when the user opens the app for the first time. I'm trying to do it "the right way", and I'm wondering about performance issue.
Currently, I have in my layout a view sets to android:visibility="GONE"
, which I change to VISIBLE
depending on a SharedPreference. This allows me to let the user learn how the app works on first launches.
What I'm wondering is what it implies when the view is rendered in my Fragment. My guess is that the view will be uselessly inflated, even if its visibility is set to GONE
.
Now, I'm thinking about an alternative: what if I would only add my View on first launches, but programmatically, in my Fragment's onCreateView
. That should allow the view not to be inflated on later launches, but wouldn't inflating the view programmatically implies bad performance on first launches?
So, to answer my own question I used the DDMS tool TraceView
to monitor the calls from my fragment onAttach
until its onResume
. It let me see which implementation are the less efficient.
To do the test, I had a simple RelativeLayout
with a FrameLayout
inside it (shown all the time). I used a custom layout to add each time, either programmatically or with a visibility of GONE on my layout file. The custom layout was composed of a RelativeLayout with 4 childs (an ImageView, a TextView, a View, and a Button).
My onCreateView
was the following, allowing the app to inflate the right layout based on two static final boolean
constants to change the layouts.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout root;
if(INFLATE_PROGRAMMATICALY) {
root = (LinearLayout) inflater.inflate(R.layout.fragment_test_prgmcly, container, false);
if(SHOULD_FYI_VIEW_BE_SHOWN) {
View tutoView = inflater.inflate(R.layout.inner_view, root, false);
root.addView(tutoView);
}
} else {
root = (LinearLayout) inflater.inflate(R.layout.fragment_test_gone,container,false);
if(SHOULD_FYI_VIEW_BE_SHOWN) {
View tutoView = root.findViewById(R.id.RL_inner_view);
tutoView.setVisibility(View.VISIBLE);
}
}
return root;
}
This lead to the following results:
When the optional layout in inflated
SHOULD_FYI_VIEW_BE_SHOWN=true
The maximum "real time estimate" given by the TraceView are of 75ms when there is just a view to change from GONE
to VISIBLE
, but of 110ms when we need to instantiate the inner_view
.
When the optional layout isn't inflated
SHOULD_FYI_VIEW_BE_SHOWN=false
In this case, the maximum real time estimate given by TraceView are of 102ms for the inflation of the GONE
view, versus 39ms when the view inflated doesn't have the GONE
view.
So, for the performance gain when the views doesn't need to be inflated, I'd say that the best solution is to inflate your view programmatically if you only need to show it a few time.
You can find the test project on a Gist
I think you are reinventing a wheel. For this scenario is already existing tool in Android xml layouts. It is called ViewStub. You can read more here: Loading ondemand
I think I just randomly stumbled over the answer of your performance question.
From the Animation Docs:
For the view that is being faded in, set its visibility to GONE. This prevents the view from taking up layout space and omits it from layout calculations, speeding up processing.
This would mean performance is not compromised as long as you don't set android:visibility
to anything else than GONE
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With