Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Layouts performance: Programmatic vs XML

As an Android developer, it bothers me not to know wether an app performance is better by declaring the layouts programmatically or by XML.

I have read this and this question on SO, but none of them answer my question:

What is more performant: writing the layouts programmatically or declaring them in xml files ?

Note that I'm only asking about performance, I don't want answers based on other factors.

Also, I'm looking for a very technical answer. If needed, please provide links to AOSP code that justifies your answer (you can assume that Android version is Marshmallow). Even better would be to point out to an experiment/paper/benchmark were the load time of a huge layout is compared using the two different ways.

like image 521
FlyingPumba Avatar asked Feb 23 '16 03:02

FlyingPumba


People also ask

Which layout is faster in Android?

Measurement results: ConstraintLayout is faster As these results show, ConstraintLayout is likely to be more performant than traditional layouts. Moreover, ConstraintLayout has other features that help you build complex and performant layouts, as discussed in the benefits of a ConstraintLayout object section.

How are Android layouts optimized?

Use compound drawables - A LinearLayout which contains an ImageView and a TextView can be more efficiently handled as a compound drawable. Merge root frame - If a FrameLayout is the root of a layout and does not provide background or padding etc, it can be replaced with a merge tag which is slightly more efficient.


1 Answers

For most practical intents and purposes, there is no significant performance impact to either approach. It might be relevant if you needed to inflate an incredibly large number of a particular layout, at which point you might try benchmarking it yourself to see if there's any real difference, but otherwise I'd be hard-pressed to envision a scenario that results in a significant impact either way.

Suppose you have a layout:

<LinearLayout xmlns:android="..."
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    ... >

    <Button
        android:id="@+id/some_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/my_button_bg"
        android:text="Hello World" />

    <!-- other views ... -->

</LinearLayout>

What happens is Android compiles this file into a binary format and packages it in the APK. When you use LayoutInflater at runtime, it will load a block of this binary format into memory and parse it, and build the view hierarchy from the contents, very similar to what you would do by hand in code. That parsing is all done in native code, so it's likely much more optimized than your typical XML parsing in java.

LayoutInflater constructs the views using reflection when it encounters a tag (e.g. <Button .../>). The first time it must look up the constructor for that particular view; thereafter it will cache the constructor for faster access later.

Where you would normally call mutators like button.setText(...), button.setBackground(...), etc., typically the views call these methods on themselves during inflation. That is, the code path being traversed through the view's constructor will perform those mutations based on the attributes parsed from the binary XML format. This is because LayoutInflater uses the two-argument constructor which accepts an AttributeSet. The implication here is that when you build views by hand, some of these methods may end up getting called twice.

For example, take the Button in the sample layout above. Buttons already have a default background (how this is actually provided is itself interesting, but not very important here), so even calling the one-argument constructor with just a Context still gets you a Button with the default background. In other words, the code path includes a call to setBackground(...) (or some equivalent) with the default background image. Then later you have to call setBackground(...) yourself with the custom drawable resource named in the XML file. It's difficult to say off hand what impact this has because it really depends on the implementation of individual views and what mutations you are making.


One final thought: I have built an app in a professional environment that avoided all use of XML (as much as possible, including things other than layouts). I can tell you without hesitation that it is immensely annoying and increases development time dramatically. I'm very good at it and it still takes far longer than doing it in XML. Additionally:

  • The code tends to be extremely verbose
  • You don't get the benefit of all the tooling built around XML layouts in the IDE
  • Even without the tooling, just the XML file alone gives you a clear representation of the view hierarchy
  • You may have to know about certain idiosyncrasies of the UI framework (some of which may depend on API level)
  • It's not always possible to map an XML attribute to a corresponding mutator method in java (again sometimes depending on API level)
  • Calculating dimensions gets a lot more interesting
  • Remembering which LayoutParams to use where is great mental gymnastics

There are probably other reasons, but those are just off the top of my head. Don't get me wrong, there are plenty of times where manual manipulation of views and hierarchies is valuable, but I wouldn't substitute inflation for that.

like image 87
Karakuri Avatar answered Sep 20 '22 10:09

Karakuri