13 12 / 2011
Improving the Android ListView
I wanted to take a few minutes to talk about my experience using the ListView in Android. For my non-developer friends, the ListView is the widget that organizes information in an item by item structure that scrolls when necessary. It’s used to implement your contacts list, among many other views in Android.
I’ll often refer to the ListView as the most important widget in the Android UI toolbox. Maybe that’s me being overly dramatic, when compared to objects like the Button, TextView, or layouts like LinearLayout or RelativeLayout. I’d argue my case by pointing to the countless examples where a ListView’s usage is critical to the mobile app it’s being used in. Think about these few examples, Google+/Twitter/Facebook, PicPlz, Gmail, Settings, Text Messages, Contacts, RSS readers, and Music. The notion of a scrollable list of information, implemented using the ListView, is at the core of the user experience of all of these apps and I’m positive you can rattle off a dozen yourself. The nature of a touch screen provides the need for information to be displayed this way, so it’s no surprise this one widget finds itself being so critical to such a huge number of apps.
The ListView is so core to so many apps, you’d think it would be a dream to work with as a developer. I’ll caveat the rest of my thoughts by saying I’m no expert, and there very well may be better ways to approach some of the scenarios I’ll bring up. But if there are, Google hasn’t been very helpful in my discovery of them. :)
In simple scenarios, the ListView is a very simple and efficient widget to implement in Android. Take the Settings app, where each item simply displays an icon and short text describing the general settings available for your device. Each item is simple and the XML layout for each is likely very compressed which leads to a truly optimal experience for the ListView. The scroll is fluid in Settings. You can flick the screen and everything behaves as you’d expect.
Looking at a more complex example, such as the Google+ app for Android, you’ll see a far more complex item structure. Each post in your stream is an item in the ListView. Each post contains a profile image for the person who posted it, their name, how long ago it was posted, it’s visibility, the text of the post, possibly a media element such as a photo or video, possibly they’ve shared someone else’s post that duplicate everything above, and finally how many +1’s and comments the post has gotten. That’s a lot of data, especially for a single ListView item. Starting at the top of your stream, if you quickly flick the screen you’ll notice images are loaded dynamically, videos begin to cue up as you fly by them, and as these things happen the UI will pause even for just a moment as it goes by each item of any complexity.
I’ve spent the last few days very focused on one task; performing any kind of optimization I can for the heavy ListViews I’m using in my next app. I’ve learned a few things along the way, some have been pretty obvious to me since starting my exploration of Android more than a year ago:
1. Caching images used in ListView items with SoftReference or WeakReference is useless.
2. Reusing the view passed to getView() in your adapter is extremely important.
3. Using findViewById() in getView() is expensive, therefore the ViewHolder pattern is highly recommended.
4. Getting a reference to the LayoutInflater is often unnecessarily done in getView(), you should get a reference to it in your adapter’s constructor.
5. Using a dynamic image in each item negates some of the optimizations I’ve outlined above.
Explanations
1. Caching images used in ListView items with SoftReference or WeakReference is useless.
Here’s an example of lazy loading images, where you’re requesting each image to be downloaded on a background thread and stored in-memory for future usage. It sounds fantastic, until you start seeing OutOfMemory exceptions after loading a number of images. The next step will be using SoftReference so that your objects can be garbage collected when necessary, but still afford you some form of simple caching. Now it sounds perfect, until you do some testing and realize that your objects are being released almost instantly as you scroll past them due to a bug in the Dalvik VM.
What this boils down to is needing to roll your own cache, for something that seems to be pretty common for ListView implementations. I would love to see a subclass of ListView added to the Support Library that implements a cache for images and improves the drawing of the list as it scrolls.
2. Reusing the view passed to getView() in your adapter is extremely important.
In the getView() method, which is called for every list item, you’re given a View. That’s a reference to the view already being shown with the idea being you can reuse it with new data, instead of inflating a new list item every time. This isn’t always possible, but it’s a must when you can do it.
3. Using findViewById() in getView() is expensive, therefore the ViewHolder pattern is highly recommended.
This is something I learned recently and it made sense when I first saw it. The ViewHolder pattern is a static class that has a variable for each UI widget in your list item XML layout. In the getView() of your adapter, you call findViewById() for each widget you need to set a value for and store the reference in the ViewHolder instance. When you’re done, you get the tag of the view to the ViewHolder. So on future calls, you can simply get the tag and have direct hooks to each of your widgets without searching your item structure using findViewById() every single time. Again, some scenarios break it’s usefulness, but use it when it’s possible.
4. Getting a reference to the LayoutInflater is often unnecessarily done in getView(), you should get a reference to it in your adapter’s constructor.
Kind of an obvious thing, but another I had never seen in code examples until recently. Most of the time you’ll see adapter implementations where a LayoutInflator is being retrieved from the system every time you need to inflate a new list item. You can move this call into the constructor of your adapter, and use the instance in getView() without constantly refreshing it.
5. Using a dynamic image in each item negates some of the optimizations I’ve outlined above.
And now for the killer. When you’re loading in a dynamic image for each list item, such as a profile image for the Google+ app, many of these optimizations aren’t possible. I’ve been unable to find a way to reuse the view being passed into getView(), because when using the ListView you’ll see incorrect images loading for items because the sequencing gets messed up. As a side effect of not being able to reuse the view passed into getView(), I’m unable to effectively take advantage of the ViewHolder pattern because I have to inflate the new list item every time anyway. It seems like doing any sort of call to load an image dynamically inside of getView() really causes poor scrolling performance in the ListView.
More Tips
A few other suggestions I’ve seen recently but haven’t investigated yet:
1. Simplify your XML structure for the list item.
2. Use RelativeLayout instead of LinearLayout in your list item.
3. On your ListView, set DrawingCacheEnabled to true to improve performance on scrolling.
While not all of these are possible due to my use case, I’m curious to dig deeper into #2 to see if I can find anything tangible. Same for #3, I’ve enabled it and it appears to perform better but it’s hard to quantify.
Conclusion
The ListView is a critical widget for any Android developer, and I’d argue it’s the most critical. It’s been at the core of every app I’ve ever built and I don’t see that changing any time soon. The ListView is powerful in it’s current state and there are little nuggets of information out there to improve it’s efficiency and power. I’d like to see the performance of the ListView improve and better support for some of the use cases that have shown since the ListView was originally developed. It’s a blind assumption, but I imagine the way we’re using ListView today is more involved than the developers originally expected and it seems to be putting a strain on what it can handle efficiently. Hopefully the above tips I’ve found throughout my searches and exploration will help someone, as they’ve appeared to help the performance of my next app’s complex ListView.
Permalink 1 note
19 11 / 2011
Yes, the Galaxy Nexus is still coming
The Galaxy Nexus has to be one of the most anticipated phones this year, if not the most anticipated. In the US, we’re still in the dark as to when we can hand over our money to Verizon and actually purchase it. This has caused all of the Android faithful, myself included, to scour the Internet practically daily to find any information about the phone we can. It’s gotten to the point where many people are getting skeptical over what’s actually going to be released.
I’m asked all the time if I’ve heard any more about the release. Rumors are flying about the Galaxy Nexus. A number of people are saying that it will have bloatware from Verizon on it, that it’s been delayed until December, that Verizon doesn’t want to release it now because it’s so close to the RAZR, that the Verizon LTE version will be wildly different than the HSPA version being reviewed by most media outlets, that it’s only coming in 32GB at a higher entry price point, and more. We can speculate endlessly about the rumors, and while I have a few thoughts of my own on why we are where we are, the fact is we have no idea.
I’ve seen people caving in and buying other Android devices, like the RAZR, as they’re unable to hold out for the Nexus. Look, I’m as excited and interested in this phone as anyone. I’m buying this, at full retail, the day it’s available. I would suggest we all step away from the ledge and relax a little bit. Yes, the Galaxy Nexus is still coming and it’s going to be awesome. If it takes another month, isn’t that worth the wait? I’m not everyone, but I genuinely have no interest in anything but the flagship phone. The only reason I don’t own the Nexus One or Nexus S is because Verizon didn’t carry them. This phone will likely last me the next 18-24 months, and the inability of not being able to wait a few weeks to get the best blows my mind. Anyone who recently bought the RAZR, or another Verizon-carried Android device, will be kicking themselves when the Galaxy Nexus comes out. Not so much just because of the hardware, but because of Ice Cream Sandwich.
The phone is coming and everything I’ve read and heard about it leads me to think it’s going to be very much worth the wait. When it finally does release, and we’re all playing around with ICS for the first time, we’ll look back at how silly the pre-release doubts and rumors really were.
17 11 / 2011
Android 4.0 will change the game
A lot of information has come out today about Android 4.0, Ice Cream Sandwich, that has really impressed me and leads me to think ICS will change everything we think about Android.
This morning I saw that ICS will prompt you to join Google+ upon activation. If you look around at all of the screenshots and videos we’ve seen from ICS in the last month, you’ll find Google+ icons everywhere in the new OS. When you view a photo, a video, or want to start a chat with your friends, Google+ is there and ready for action. Google+ appears to be a huge part of ICS and with 200 million Android devices having been activated, 100 million of those since just May, you can expect a huge surge of Google+ accounts. With all of the sharing features built-in to ICS for Google+, perhaps a number of those accounts will remain active as well. Apple boasted it’s deep Twitter integration with iOS 5, and Google is responding to that by integrating a more comprehensive social network deeply into ICS. While Google+’s usage isn’t where Twitter is today, I wonder how Twitter (and Facebook for that matter) feels about seeing Google+ so tightly integrated with an OS that will land on well over 200 million phones, tablets, and TVs in the next 6-12 months.
In the same article, it mentions that you’re also asked to enter a credit card for your Google account. This is huge news that should provide a major boost to the Android developer ecosystem. How many times have you visited the Market, found an app you wanted to buy, only to realize that you don’t have a credit card on your account? So instead of fetching your card to complete the purchase, you just hit the home button and forget about it. I’ve done this, many times. The “accounts with credit cards” metric is fantastic for both Apple and Amazon, and hopefully now Google will join the club. More people will have instant access to buy from the Market, a major reason why the Apple App Store and Amazon’s web/content business have been so successful, so there’s plenty of reason to believe Android will reap similar benefits. More developers making money means more developers creating better and better apps.
Later in the day I noticed that Google has made a solid decision in the marketing effort for ICS. While I am one of those people who like the Droid commercials from Verizon, I would also agree they’re not very useful for describing what a consumer is purchasing. They make for fun commercials, like an over-the-top Michael Bay film, but that’s about it. Google has released a series of videos outlining some of the features of ICS, all of which feature humans. These are the kinds of commercials Apple puts together to sell to the general public, not nerds like you or I, and it works, it really works.
Then I saw that Android.com had received an overhaul to become more consumer friendly. In the past this page was mostly geared towards developers and now it’s serving the purpose it really needs to serve. The Galaxy Nexus page at google.com/nexus received a big overhaul as well, also focused on consumer friendly information about the new flagship Android device. These consumer focused efforts haven’t really existed for Android previously, and I’m glad Google is realizing the need to focus at least some marketing efforts on being consumer friendly. This won’t change the Droid commercials, for obvious reasons, but it’s a positive step for the flagship device and for the platform itself.
Tonight The Verge published their review of the Galaxy Nexus. The review was done by Joshua Topolsky, someone I would typically classify as being firmly in the Apple camp. His review was overwhelmingly positive but what stands out most to me is he gave each the software and performance a 10. While he doesn’t classify it as a perfect device, mostly due to the camera not being quite on par with the iPhone 4S, which is really a great camera I have to say. He does provide some great quotes for the Android faithful:
The Galaxy Nexus is the best Android phone ever made. It’s one of the best smartphones ever made, and with a couple of minor tweaks (particularly to the camera), it could be the best smartphone ever produced.
Still, there’s really not much to knock here. The hardware is elegant and smartly designed. The software is beautiful and useful. Google has cleaned up a lot of the bad, and replaced it with a serious amount of good. It’s faster, smarter, and a lot more friendly than any of its predecessors. Ice Cream Sandwich easily gives iOS and Windows Phone a run for their money, and in many ways, it’s a superior operating system than either of them.
Android is maturing, quickly. Google is boosting their social network by integrating it more deeply into the Android OS and having people sign up when they activate a new device. They’re making the purchasing process more frictionless by having people enter payment details upon activation. They’re refining their marketing effort such that your average consumer will grasp it and enjoy it. They’ve evolved an excellent base OS to a more consistent, performant, and responsive platform where even the harshest of critics are praising it. Android, the platform with over 200 million activations, the OS we already love, got an order of magnitude better in just under a year. Are you excited yet?
31 10 / 2011
Understanding Android Resources
A lot is made of Android fragmentation these days. It’s hard to read a popular tech blog without at least a mention of the “massive fragmentation of Android”. It’s a popular thing to say, and keeps the Apple followers (see what I did there?) happy with said publication.
Some of the concern is related to the physical differences in devices such as software/physical keyboard, with/without GPS/camera/etc. These are justifiable concerns, certainly, but nothing that difficult to manage. The manifest file associated with every Android app gives you the necessary flexibility to manage which features of your app are required or not. So, if a GPS is absolutely required for your app, you can use the manifest to tell the Android Market to filter your app out of results on devices that don’t have a GPS. Simple.
Using the same example, if a GPS is not required, but is a nice additional feature for the experience, you can declare the feature usage optional. So, the app will show for devices with or without a GPS. Then at runtime, you simply need to detect whether the presence of a GPS should alter your workflow or UI. In many cases you can easily use reflection to determine what is or is not available. There can be outliers, certainly, but this is how physical fragmentation is handled in most scenarios.
I think more of the fragmentation is aimed at the variations of device screen sizes. You can look at the Droid, the Incredible, the Droid X, the Bionic, the Dell Streak, and the Galaxy Nexus to see a variety of screen sizes. What Android does is deal with these variations by creating a few general categories that all devices fit into.
There are four generalized buckets for size (small, normal, large, and extra large). There are also four buckets for density (ldpi, mdpi, hdpi, and xhdpi). Android puts each device into a combined bucket based on size and density. You can find a nice chart overview of those here: http://developer.android.com/guide/practices/screens_support.html#testing.
So while every chart or graph you’ll find on your favorite tech blog shows the countless configurations for Android devices, the truth is that 90% of the Android devices being tracked by Google fit into just 2 buckets (http://developer.android.com/resources/dashboard/screens.html). Both buckets are of the same size generalization, and really only differ in that 17% offer 160 dpi and the other 72% offer 240 dpi.
What that boils down to for the developer is simply two sets of images, one for mdpi (160 dpi) and one for hdpi (240 dpi) and one layout grouping (large size generalization, views for both portrait and landscape).
So, as Cyanogen asked on Twitter the other day, who’s really worried about fragmentation?
You’ll find a great explanation of how Android handles sizes and densities, from the perspective of a developer, here as an answer on StackOverflow.
28 10 / 2011
"Dear Apple, Please Make My iPhone 4S Battery Life Suck Less"
26 10 / 2011
Android 4.0 - Face Unlock
I’ve seen a number of podcasts and blogs where the face unlock feature of Android 4.0 has been questioned on it’s performance and whether it will be used in the wild. A number of people are chalking it up to be like FaceTime on iOS; a great tech demo but not something people use very often, if ever.
While we won’t know how often it’s used until the OS is actually available, there are two things that will determine if it’s going to be used by most people. Does it work, and how quickly does it recognize my face?
While the stage demos in Hong Kong weren’t overly successful, I’ve seen enough videos of the Galaxy Nexus with Android 4.0 to know it does work. Perhaps available light effects it’s ability to detect your face, but we won’t know for sure for another couple of weeks.
The biggest gripe I’ve heard is how quickly the scan performs. A recent TWiT episode, I believe it was This Week in Google actually, seemed to be less than optimistic on the performance based on the demonstrations we saw at the unveil. I have to believe Google realizes that these two factors are critical to the success of this feature, which given how often you’re going to use it, appears to be a pretty importance piece of Android 4.0.
I ran across these videos today, and was happy to see how quickly and well the face unlock feature was working in a soup to nuts demonstration.
http://androidcommunity.com/samsung-galaxy-nexus-on-amazon-uk-ships-november-2nd-20111026/
Second video, skip to 5:40. The whole video is a good watch if you’re interested in more Ice Cream Sandwich.
26 10 / 2011
Android 4.0 Consistency
The more I see from Android 4.0, the more excited I get. I went through two articles today from Android Police which detail the differences between Gingerbread and Ice Cream Sandwich versions of Gmail and Google Talk. The differences are dramatic even though the core stays the same. The consistency between the two, and refinement of contextual actions in the way of the split Action Bar, is such a huge improvement I can’t overstate it enough.
I would encourage you to look through both of these articles and notice the consistency improvements we can expect with Android 4.0. This is what I think Android needed more than anything and I’m very happy to see it happening.
Gmail: http://www.androidpolice.com/2011/10/22/getting-to-know-android-4-0-part-1-gmail-androids-most-important-app/
Google Talk: http://www.androidpolice.com/2011/10/26/getting-to-know-android-4-0-part-2-google-talk-gets-a-facelift/
18 10 / 2011
Android 4.0 - Ice Cream Sandwich
To say I was nervous about what we were going to see from Google for Android 4.0 was an understatement. I really felt that the unification of the phone and tablet platforms was going to be the big feature, and perhaps it will turn out to be. Yet, as I watched the presentation of what’s new in ICS, and what the motivations were for the changes, I was very impressed. In my mind, there are three big takeaways from the introduction to ICS:
1. Platform consistency
One of the biggest points of frustration for many Android users is the lack of consistency across the UI and how you access various parts of the OS. You can really see the investment made in ICS to make the experience feel more consistent. It’s a very welcome addition for me, and I suspect most everyone else, and in my mind is the killer feature for the OS. It’s what Android needed more than anything else, and you can see the Android team knew that and put forth a lot of effort to make it so.
2. It brings the innovations of Honeycomb to the phone.
Honeycomb hasn’t gotten a lot of love, and in many ways I can understand why. What does deserve some attention are the various ways Honeycomb innovated on Android 2.x. With ICS, these innovations are felt across the Android platform and will get the much needed exposure. Things like one-button access to multi-tasking from any screen, software buttons instead of physical buttons that are intelligent and can adjust to context, the Action Bar and it’s context-aware nature, much improved widgets that are resizable and more interactive, tabbed browsing, cloud-enabled browser bookmarks across your mobile devices and desktop, and more. For me these are all features I’ve been enjoying since March, but as was pointed out to me on Google+, the vast majority of Android users have never used a Honeycomb device. These additions will change Android for the better.
3. A unified experience for phones, tablets, and more
While this may feel natural, and not so much a feature, I think understating this point would be shortsighted. For consumers, having a consistent experience across our Android devices will be a welcome shift and yield better apps for the platform. For developers, we’ll be able to focus on building towards one platform and one experience. While the screen sizes will vary, the idea of the Action Bar that is so fundamental on the tablet will help us unify our efforts in building great apps for the platform.
Overall, I’m very pleased with what we saw today of ICS, and that’s not even commenting on the Galaxy Nexus (read: drool…). The minor touches like unlocking your device from face recognition, unlocking directly to the camera, pulling down the notification area from the lock screen, having a consistent way to dismiss things (notifications in the notification area, running apps in the multi-task view, open tabs in the browser, etc), and the overall attention to UI and polish (an entirely new typeface across the platform, for example) are all fantastic. Google really just stepped up their game, and I wasn’t expecting that at all.
19 8 / 2011
Okay HP, Let’s Make Some Lemonade
So, they’re suggesting HP should do what Google (mostly) did with Android, and yet they bash Google constantly on how they’ve handled Android. Got it.