Tuesday, March 2, 2010

Progressively loading ListViews

Again I received a mail from somebody who asked for lists with forward/backward paging option. These lists are not trivial to implement but I was more intrigued by the need why anyone would want such a clumsy UI construct. Then it turned out that the guy wanted to back the list with data from a web service. Obviously, he did not want to wait until the entire list is loaded through the network but wanted to present something to the user as soon as possible.

Such a list can be found in Android Market when the list of applications is progressively loaded from the network server. The problem is worth a simple test program to analyse because it clearly shows the power of the Android adapter concept.

Click here to download the test program.

Our test application does not actually connect to the network but simulates the slow data source. If you check the Datasource class, you will find that even though this "data source" is a simple array, the accessor method adds a 500 ms delay to every access. This simulates well the fact that loading from certain data sources takes time. The trick is in the PageAdapter class. This class adds a View to the end of the list ("Loading ..."). Android Market animates this view but the idea is the same. Whenever this View is drawn, the adapter kicks the loading thread which progressively fetches new elements from the data source, adds them to the Adapter's data set and notifies the adapter that the data set has changed. There is the usual fiddling with a Handler to make sure that notifyDataSetChanged() is invoked in the context of the UI thread. The Adapter constantly changes the value returned by the getCount() method as the items are loaded from the data source. When the whole data set is loaded, the "Loading ..." widget is not drawn anymore therefore nothing triggers the loading thread.

Here is how it looks like.



No, wait a minute, here is how it looks like.


Yes! After having blogged for more than 2 years about Android, I finally put my hands on an actual Android phone. The story is complicated but the essence is that a friend thought that I deserved that phone and gave it to me. Thanks for everyone involved!

11 comments:

Istvan Farkas said...

Wow, congrats!
I couldn't agree more with your friend, you have deserved it!

Anonymous said...

cool man..

Christopher said...

You need to check out all the commonsware stuff:

http://github.com/commonsguy/cwac-endless

Gabor Paller said...

I checked it out. :-)

Here is the result.

genxsol said...

good tutorial but
i need progressive loading ListView for my custom list.
my list item consist of an icon and two text fields.
please share if anybody got any example for this?

Gabor Paller said...

genxsol, adapt this blog entry:
Custom widget adapters

Then update getView() in PageAdapter as shown by the custom widget adapter example.

codeScriber said...

Just a small info :-)
with eclipse and ddms.bat you can take snapshots of the current screen,of course u need the device to be hooked up with USB cable :-)
10x for the tutorial, i'm trying to figure out if a fellow worker's code is good or not (it's actually an expandable list).

10x Again.

Anonymous said...

Please! Somewhere in the process of taking that picture, transferring it to your computer and uploading it to your, you should have realized that it is a truly crappy photo!

Yinten said...

http://www.ryangmattison.com/post/2011/08/22/Reverse-Paginated-List-View-(1-3).aspx

Robust Reusable Paginated ListView Tutorial

Anoo said...
This comment has been removed by the author.
Anoo said...

Hey,

Thanks for this great tutorial. I am following this rather than CW-Endless Adpater. But my data is not set on the listview. Rather it shows me Loading symbol only. Please help. Below is my getItem() method. Have been stuck for few days.

public HashMap getItem( int itemIndex ) {
// It's a slow data source
if(!requestparameter.equals(""))
new LoadAllAds().execute();

return productsList.get( itemIndex );
}