Creating Android layouts that look good can be challenging. Once you’ve spent hours tweaking them to suit multiple devices, you often won't want to revisit them. However, bulky, nested layouts can be tremendously inefficient. Luckily, there’s a tool available in the Android SDK that can help optimize your project layouts to decrease memory usage and improve performance.
Optimization is always tricky business. Having good, well behaved, high performance code is great. But at what cost? You never want to prematurely optimize or spend too much time on code that may only run once or is in a short-lived feature. On the flip-side, if your application is unresponsive, takes up too much memory, or slows down the rest of the system users will notice and your application downloads will likely suffer.
Optimizing your layouts fairly early in the development process is one easy way to save memory and increase performance. Some changes will be negligible, others may be quite noticeable. The Android SDK comes with a tool to automatically analyze your layouts and find potential areas of unnecessary layout complexity.
Step 0: Getting Started
In order to use the layout optimization tools provided with the Android SDK, you need to be comfortable working at the command line on your development system. If you aren't familiar with command line tools and how to access the command line on your particular operating system, you will need to come back when you are. This isn't a tutorial on how to use the command line on various operating systems.
We highly recommend that you add your Android tools paths to the path setting for your operating system. This will make it much easier to run specific tools by name, without having to give the full path to their file location. There are now two tools directories in the Android SDK: /tools and /platform-tools. The layoutopt tool, which is the primary tool used in this tutorial, is found in the /tools directory. (The ADB tool, for instance, is found in the /platform-tools directory.)
Running the layoutopt tool is straightforward with easy command-line options. Simply run it with a single layout file or a directory of layout files as the option. The main caveat here is that you must include the full path to the layout file or directory in question, even if it's in the current working directory.
Let’s look at a simple, working example of a layout file that doesn't have any issues found by layoutopt:
D:\d\tools\eclipse\article_ws\Nothing\res\layout>layoutopt D:\d\tools\eclipse\article_ws\Nothing\res\layout\main.xml D:\d\tools\eclipse\article_ws\Nothing\res\layout\main.xml D:\d\tools\eclipse\article_ws\Nothing\res\layout>
Notice in the above example that the name of the file checked is shown. If you don't include the full path to the layout file or files, the output shows nothing. For example:
D:\d\tools\eclipse\article_ws\Nothing\res\layout>layoutopt main.xml D:\d\tools\eclipse\article_ws\Nothing\res\layout>
Thus, if you see nothing, then the file wasn't parsed even though no errors show indicating that the file wasn't found.
Examining layoutopt Results
The results of layoutopt are only suggestions. You can pick and choose which items to incorporate into your application. But, why would you be running the tool to just ignore its output? Let's look at a few examples of the suggestions that might result from running the layoutopt tool.
Sometimes we move things around so much during layout design that we end up with unused or abandoned controls. Take this layout, for example:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <LinearLayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:text="TextView" android:layout_height="wrap_content"></TextView> </LinearLayout> </LinearLayout>
The tool will quickly tell us that a LinearLayout within a LinearLayout is unnecessary:
11:17 This LinearLayout layout or its LinearLayout parent is useless
The two numbers at the beginning of each line of output indicate the line numbers of the suggestions. This is usually the end line of the opening tag and the closing tag. We've highlighted these in the XML listing above.
Root Can Be Replaced
Sometimes the output from the layoutopt tool can seem to be contradictory. For instance, take this layout:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:text="TextView" android:layout_height="wrap_content"></TextView> <TextView android:text="TextView" android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> </LinearLayout> </FrameLayout>
This layout will result in the following output:
5:22 The root-level <FrameLayout/> can be replaced with <merge/> 10:21 This LinearLayout layout or its FrameLayout parent is useless
You have to read both items before you can decide what to do. The first line, although true, is not necessary. We know we want both text views to be stacked vertically, so the LinearLayout should stay. Thus, based on the second line, we can remove the useless FrameLayout and not replace it with a merge.
Interestingly, the tool isn't all-powerful. For instance, in this example, if we add a foreground attribute to the FrameLayout and rerun the tool, the first warning will -- correctly -- disappear, but the second warning will still be shown. The tool knows that we can't control the foreground with a merge, but once it has moved on the LinearLayout, it seems to forget that the FrameLayout was providing an attribute that LinearLayout can't provide.
Too Many Views
Each view in a layout uses memory. Put too many views in a layout, and the layout will use too much memory. Imagine a layout with more than 80 views. The layoutopt tool might display the following types of output:
-1:-1 This layout has too many views: 83 views, it should have <= 80! -1:-1 This layout has too many views: 82 views, it should have <= 80! -1:-1 This layout has too many views: 81 views, it should have <= 80!
The number of views are calculated at each level. (Though, you might notice in the above run that the output doesn't show which specific view is being referred to.) The suggested limit to views of 80 is just that: a suggestion. New phones and devices may do just fine with that number of views. However, if the layout performs slowly on some phones or if there is lag or stuttering when scrolling around on such a layout, this would be a likely candidate as to why.
Too Many Levels
Along similar lines, layouts should not be too deeply nested, in terms of parent and child layouts. The tool (and the Android team) recommends keeping layouts under 10 levels deep. Considering the size of even the largest tablet screens, most layouts should be far shallower than 10 levels. If you find yourself continually making very deep layouts, we would suggest really looking closely at the RelativeLayout control, as it can usually be used to keep otherwise complex layouts fairly flat. RelativeLayout can be a bit trickier to use, but the latest updates to the Graphical Layout resource tool in Eclipse certainly make this easier.
In any case, here's a sample output from a layout that's far too deeply nested:
-1:-1 This layout has too many nested layouts: 12 levels, it should have <= 10! 305:318 This LinearLayout layout or its RelativeLayout parent is possibly useless 307:314 This LinearLayout layout or its FrameLayout parent is possibly useless 310:312 This LinearLayout layout or its LinearLayout parent is possibly useless
The nested layout warning will typically be accompanied by warnings of possible useless layout widgets that can help assist in finding which layouts to remove, short of a full redesign of the screen layout.
The layoutopt tool is a fast and easy tool to analyze your layouts to look for possible inefficiencies and useless layouts. You still have to make the decision yourself as to how to deal with the optimization suggestions. Making the suggested changes won't (usually) suddenly make your perform hugely better, but there's no reason to have an overly complex layout that is slow, inefficient and more difficult to maintain. Simplified layouts simplify testing and maintenance, so optimize your layouts earlier in your application development so you don’t have to retest at the last minute. There are almost always several ways ways to design a similar screen. Regardless of the method used, the layoutopt tool can shed light on potential inefficiencies with your method.
About the Authors
Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams Teach Yourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to email@example.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.