Later in the day at Google I/O 2009, we had Romain Guy’s presentation, â€œTurbo-Charge Your UI: How to Make Your Android UI Fast and Efficientâ€. UI performance not only can affect users directly, in terms of how quickly they can use the activity, but also indirectly, in terms of battery life or affecting other applications due to garbage collection.
First, Romain covered adapters, those objects that convert a collection of model objects into row views for a ListView, Spinner, or similar selection widget. Adapters can blindly create new rows for every model object that gets displayed, but that is inefficient. Instead, ideally, an adapter will recycle row views, binding new model data to the existing view, saving us constructing all those widgets and containers that make up the row. The Fancy ListView series in this blog covers recycling rows in this fashion, along with related techniques such as using view holders or wrappers. Using these techniques could result in as much as a 300% improvement in list-scrolling performance.
Next, Romain moved into images, particularly backgrounds for widgets. Backgrounds will always be fitted to the widget, and so Android may have to scale your bitmap to fit the widget â€“ however, scaling at runtime is expensive. It is better, where possible to pre-scale the image and use the scaled one in your layouts, rather than having Android scale it on the fly. You can do this in Java code, via Bitmap#createScaledBitmap(), and setting the widget background from the cached scaled value.
Romain then moved on to manual redrawing, using methods like invalidate(). You may feel you need to do this, in cases where you have modified widgets but the changes do not seem to take effect. However, invalidate() is rather expensive if you try to invalidate the whole screen â€“ use other versions of the validate() method to redraw only small portions of the screen containing the regions truly needing to be redrawn. There is a â€œShow screen updatesâ€ option in Dev Tools that will help you see what portion of the screen you are actually invalidating.
The next topic was views, particularly view hierarchies. The more views you have on-screen, the slower that screen will perform. This is especially true for deep view hierarchies, which eventually can trigger a StackOverflowException if they get too complicated. Use tools like hierarchyviewer to analyze your UI and see what might be removed, as discussed elsewhere in this blog. He also covered some specific ways to get rid of extraneous widgets and containers, such as ViewStub and the <merge> element in layouts.
Romain wrapped up with a discussion of memory allocation. The less you allocate, the less garbage you create, and the less frequently the garbage collector will steal away CPU time from your application. In particular, try to minimize allocating memory in frequently-invoked methods, like getView() in an Adapter. You can use setAllocationLimit() on the Debug class during development to have Android raise exceptions if you allocate more than a specified amount. Also, use the Allocation Tracker tool as Jutstin Mattson described in a previous Google I/O session.
Update: Here is the video for this session: