Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Performance : Adding view programmatically vs setting view to GONE/VISIBLE

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?

like image 292
MagicMicky Avatar asked Jul 08 '14 13:07

MagicMicky


3 Answers

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

like image 183
MagicMicky Avatar answered Oct 20 '22 22:10

MagicMicky


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

like image 7
user123 Avatar answered Oct 20 '22 22:10

user123


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.

like image 2
ntv1000 Avatar answered Oct 20 '22 22:10

ntv1000