|Android Adventures - ListView And Adapters|
|Written by Mike James|
|Thursday, 08 October 2015|
Page 4 of 5
Reuse, Caching and General Layouts
We have a working custom adapter class but there are some things we can do to make it better.
The first relates to efficiency.
If you recall it was pointed out that a big list of objects could result in the creation of a lot of View objects. In practice however we really only need the number of View object that correspond to rows actually being displayed on the screen.
To avoid having to dispose of and create new View objects all the time the ListView gives you the opportunity to recycle the View objects you have already created. This is what the convertView parameter in the getView method is all about. If it is null you have to inflate and create a new View object. If it is non-null then it is a View object ready to be used and you don't have to create a new one.
Modifying the previous example to make use of convertView is easy:
This is a speedup worth making and saves having to create lots of View objects and disposing of them.
However we are still looking up the child View objects every time we want to change the data. That is:
This is also very wasteful and can be avoided with the application of the ViewHolder pattern.
All we have to do is save the references to the children in an object and store this in the parent View's tag property. Then the next time we see the parent View we don't have to find the children we are looking for - they are stored in the parent's tag as a ViewHolder object.
First we need to create a ViewHolder object:
Notice that this has fields capable of holding references to our two TextView objects.
The logic of the getView method is now to also create and store a ViewHolder object if we are not recycling a View object
Notice that we have stored the references to the TextViews in the viewHolder and stored this in the row's Tag field - this is what tag fields genreally are used for.
If we do have a recycled View object then we just need to get the viewHolder object:
Finally no matter where the viewHolder object came from we just use it:
With this change we have avoided creating a View object each time and we have avoided having to lookup the child objects each time - very useful savings in time and resources.
Finally there is one last polish to apply. At the moment the layout for the row has to have the ids of the TextView objects set to title and number. Much better to let the user set these in the constructor:
This constructor has two extra parameters used to specify the id numbers of the two ViewText objects in the layout. These are stored in private variables for later use - and we need to declare the private variables:
The original constructor can still be retained as long as it sets resTitle and resNumber:
Finally we need to change the getView method to use the two new private variables:
With these changes the adapter can be used as:
and the user is free to use any ids for the layout as long are there are two TextViews.
What Is Missing?
As with all things, there are aspects of the ListView that haven't been covered. In particular, what do you do if your data structure isn't an array?
The ArrayAdapter can handle Lists, simply override the appropriate constructor. Anything more complex and you will have to create a custom Adapter. In most cases, however, this isn't necessary because most data structures can be mapped onto an array.
There are a range of formatting topics not covered - the header and separator for example - but these are relatively easy.
More complicated are the multiselection options and any custom list displays such as a list with multiple columns or pop-out detail windows.
|Last Updated ( Saturday, 15 October 2016 )|