ListView with Images [Android]

October 21, 2013 · Posted in Development 

This post shows how to get ListView with images using ArrayAdapter with custom objects.

In this example we will show a list of products with image and title in ListView.

Data

Create a class to store data about Product. Each product object contains title and image specifying by URL.


 

Custom Adapter for ListView

Create the layout for one row in the ListView. It will show product’s image and title.

Layout file “res/layout/list_item.xml”:  

 

Now we are ready to create a custom Adapter.

File ‘src/com/example/mysamples/ProductListAdapterSimple.java’:           

 

Note that this adapter is NOT optimized for showing many rows. Read how to optimize it below in this post.  

Optimize ListView with images fron Internet – asynchronous image downloading

In order to download images we used class ImageDownloader from The Android Open Source Project.    

Find the source of this class here and save it to file “ImageDownloader.java”.

This class provides caching and asynchronious downloading of images. Here we used function ImageDownloader.download which downloads the specified image from the Internet and binds it to the provided ImageView. The binding is immediate if the image is found in the cache and will be done asynchronously otherwise.

It means that images are downloaded in background thread and it doesn’t block the main thread (the UI thread).

Main Activity

Create the layout for our Activity which shows ListView. File “res/layout/main.xml”:

Activity:         

 

Here, we populate the list with some data manually in the code. Read below how to populate data dynamically from the external source.  

 

The final application will look like this:    

Find all sources for this example on Github Gist or download the full project from Github.    

 

Optimize ListView for many rows

If we have many rows in our ListView then it will not show images smoothly when scrolling. This happens because for the rendering of each row it creates a new view and it takes every graphic component from it.

 

Do not call findViewById() frequently during scrolling

Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. These operations are costly in terms of memory and cpu. Read more about it here.  

To avoid this we use “view holder” design pattern. It means that the elements of the list are recycled as they enter/exit in the portion of the ListView visible in the display.

 

Create a class ProductViewHolder to hold set of views in one row and modify our adapter:

 

Use our new Adapter in Activity:

Change these lines  in Activity class:

lvProducts = (ListView) findViewById( R.id.list_products);
lvProducts.setAdapter(new ProductListAdapterSimple(this, products) );

to this:

lvProducts = (ListView) findViewById( R.id.list_products);
lvProducts.setAdapter(new ProductListAdapterWithCache(this, products) );

 

 

Note that Android renders the rows which have to be showed. When rows disappear from screen they are destroyed.

 

ListView with images optimization  – Avoid image downloading during scrolling

First optimization with downloading images in background threads may cause many tasks if user scrolls very fast.
Thus the performance may decline significantly.

We will use the ScrollListener to avoid images to be downloaded while we scroll. It will start downloading images only when the ListView is stopped scrolling.  Also we assign a default image which will be displayed while the ListView is not stopped and until the actual image is not loaded.

Note that you should have a drawable resource. In this example, it uses image file “spinner.png” in folder “res/drawable”.

Modify our Adapter class:

    The Activity should implement OnScrollListener:

 

 

 

Populate data from external source

Often data rows in ListView are dynamic and populated from some source. In our example products might be populated from the database from the server script which returns rows in JSON format.

Having a server script which return JSON we can modify our Activity to consume data from JSON array:

 

 

 

Multiple columns

One of the ways to make a View with multiple columns is using GridView.

Read this tutorial “Showing images in GridView with multiple columns [Android]“.

 

Useful Links

- Making ListView scrolling smooth – http://developer.android.com/training/improving-layouts/smooth-scrolling.html

- Multithreading for Performance – http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

- ListViewAnimations – library that allows developers to easily create ListViews with animations

Comments

  • Alok Verma

    on back press it show a error message

    Unfortunately app has stopped

    how to solve this?