Android ListView with separate headers and images loading from remote server

ListView is easily one of the most frequently used components in Android development. While implementing a standard list of simple text items or local images is straightforward, things get tricky when you need to introduce distinct visual sections or category headers. Historically, Android didn’t provide an out-of-the-box, intuitive method to handle section headers seamlessly.

A while back, developer Jeff Sharkey demonstrated an elegant workaround for creating a sectioned list view. However, his implementation was limited to loading static images from local resources. Like many of you, my specific project required pulling dynamic image data from a remote server without locking up the UI.

By combining custom adapters with an asynchronous image loader, I managed to build a smooth, high-performance solution.


Android ListView with separate headers

To get started, we need to define two distinct XML layout configurations:

  1. demoheader.xml: Defines the visual layout for the section titles/headers separating your content.
  2. demorow.xml: Defines the layout structure for the individual rows that appear beneath each header (containing the text and an image placeholder).

We utilize two crucial utility adapters to split up our data cleanly:

  • SeparatedListAdapter: The core controller that accepts individual sub-adapters and organizes them into visually distinct blocks.
  • ObservableAdapter: A helper class that links up with the SeparatedListAdapter to let it know whenever underlying section data changes or needs to refresh.

In your onCreate method, initialize the SeparatedListAdapter by passing the context and your demoheader.xml layout.

Next, we establish our data structures to represent the contents of our sections. For instance, we can configure two distinct lists composed of key-value maps to hold our text labels and asset URLs:

Java
List<Map<String, ?>> sectionOne = new LinkedList<Map<String, ?>>();
List<Map<String, ?>> sectionTwo = new LinkedList<Map<String, ?>>();

Each map item in these lists stores the relevant data strings alongside the remote image URLs that need to be fetched over the network. You can view the full mapping integration pattern inside the MainActivity file of the source code.

Inside the main application logic, I built a custom ExAdapter class that extends CursorAdapter. This adapter acts as the bridge that populates our rows and dynamically triggers our network requests.

To keep the UI smooth and prevent lag while scrolling, the ExAdapter hands off the image requests to an ImageThreadLoader class. This loader fetches image assets asynchronously in the background and implements a dual-layer caching strategy:

  1. Disk Cache: Stores the images locally on the device to avoid repeated network usage.
  2. Soft Reference Cache: Temporarily holds images in system memory for instantaneous rendering during scroll events while remaining garbage-collector friendly.

That’s all it takes to keep your UI fluid while handling complex layouts! You can grab the full source code and explore the demo application over on the project repository page.

If you have any performance optimisations to add or run into any integration questions, let’s talk about it in the comments below!

5 Comments

  1. Wow. There are lots of wanna-be tutorials describing sectioned listViews.

    This is the most complete, and yet clear enough to understand, code for this problem that I’ve seen.

    Of course, everyone will need to tweak to adapt it to our needs, but that is expected. It really is that good.

  2. Thank you very much for your tutorial and code. But there is something I need to change inside this adapter. I need to set the item view not a single but multiple view types? for that I think I need to override getItemType() but I couldn’t do it. Can you give me a hand, thanks

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.