Home > Android > Of Rubber Stamps and CheckBoxes: Why your Android ListView is broken

Of Rubber Stamps and CheckBoxes: Why your Android ListView is broken

There are a lot of tutorials on how to use ListViews, the ubiquitous UI element in which a list of information is presented in a linear, scrolling view.  However, I do not think they do enough at explaining just why they behave in the way they do, especially with respect to stateful UI components. 

An example list view, with a very simple "view" for each row

The problem is, people do not quite understand what it means for views to be reused in the context of a ListView. This blog post is intended to explain what that means, and what consequences that has for your list views and your adapters.

The following description comes from the Swing documentation on how JTables are rendered, but it is instructive for this description, and introduces the central metaphor that helps explain what’s going on with the way ListViews are rendered.

Before you go on to the next few tasks, you need to understand how tables draw their cells. You might expect each cell in a table to be a component. However, for performance reasons, Swing tables are implemented differently.

Instead, a single cell renderer is generally used to draw all of the cells that contain the same type of dataYou can think of the renderer as a configurable ink stamp that the table uses to stamp appropriately formatted data onto each cell.

Why would the designers implement the rendering this way?  Imagine if each row of the table (or list) were a separate object.  Each row would hold references to its own UI widgets, e.g. for TextViews (labels), ImageViews (images).  If there were N rows and each row takes on average M bytes of memory, you’d have an average memory footprint of N*M bytes.  Given that these lists need to be able to display a large number of items, this would be an unacceptable memory footprint.  Furthermore, since most of the list would be offscreen, most of the memory would be completely wasted.  While it would be simpler to implement, it would bring any Android phone to its virtual knees.

The designers, borrowing from the Swing designers, chose instead a much more memory efficient way of rendering the lists – if only X items are visible on the screen, where X is much less than N, the total memory footprint would be X*M bytes.  It takes more work in the ListView class to calculate exactly which rows are visible and to ensure that only their views are rendered, but it’s worthwhile.  Each visible row uses its own “rubber stamp”, filling in the details specific to that row. 

What you do by defining your adapter view in XML is define the raw features that make up your rubber stamp.

This is the basic rubber stamp that might be used for displaying tweets in a Twitter application.  There are four elements: an image, a username label, a paragraph text label, and another label for how the tweet was posted.
Let’s say that at most four tweets can fit on the screen at once.  When the first row needs to be rendered, the view is null (hasn’t been instantiated) and must be inflated from XML.  This process is repeated for the second and third row.  When the next tweet needs to be loaded on the screen, it can reuse the view (rubber stamp) of the view that’s just left the screen at the top.

Row views are reused

This leads us into what trips a lot of Android developers up.  You cannot maintain state within the UI components alone.  What do I mean?  You cannot use, for instance, Checkboxes in each row and hope to have them keep track of which items are checked or not.  Why?  This will work for a small number of rows, but once you get past the number that can fit on one screen, you’ll start to see weird problems.  If you can fit X rows on the screen, then item 1, X+1, 2X+1, … will all share the same checkbox.  Thus by changing the state of item 1, you will change the status of all the rows further down the line that are a multiple of X away from it.  The correct way of handling this is to have each row data object, that which is being visualized by the Adapter, maintain this state.  You can see an example of this in a tutorial on how to use checkboxes in listviews. I see this question come up repeatedly on StackOverflow, and it stems from the programmer not understanding how these views are reused in each row.
The metaphor of the rubber stamp fits more with that of JTable rendering, where there truly is a single component that gets reused over and over again, whereas there are multiple reused row View objects in the case of Android.  Why isn’t the single component approach used for Android?  At first I assumed it was, until I read this great explanation on android.amberfog which illustrates how there are actually as many views inflated as there are potential rows visible at any time.  The reason as far as I can imagine is that the user needs to be able to interact with each rows.  If all that was required was the static view of each row, then it would be fine to use a single rubber stamp, render a row, change an offset in the graphics context, and render the next row.  As it stands, however, each row needs to be able to detect when it is clicked on, long clicked on, etc.  Furthermore, each row could have UI elements which themselves could be interactive.  Thus it is insufficient to present static views of the data; the user would be unable to interact with the rows in the way he expects.
I hope this explanation is helpful, and if I’ve gotten anything wrong, I’d love to hear about it in the comments.

(All images were created with the use of Balsamiq, a great tool for mockups).

  1. May 25, 2011 at 4:36 am

    You’re right!!..This is a great explanation of reusing views. I’ve been dealing with these until I understood how they work.
    I’m gonna write a technical article about it…

    Thanks for sharing this…!!!

    • i82much
      May 26, 2011 at 5:14 am

      Hi Fernando –

      Thanks for the kind words, and I’m glad the post was useful to you. When you do write your more technical discussion, please let me know and I’ll link to it

  2. brinda
    August 1, 2011 at 9:09 pm

    Another interactive prototyping tool you might want to check out is Mockuptiger, you can create, share and preview Web and mobile HTML prototypes. The key is that you can create interactive HTML prototypes with navigation which you can view and test in any browser.

    • Nicholas Dunn
      August 1, 2011 at 9:19 pm

      Cool thanks for the info.

  1. July 26, 2012 at 9:01 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: