In order to make scrolling through out lists as smooth as possible, we need to ensure that the construction and manipulation of the items run as fast and as efficiently as possible.
One way in which we can optimize the list items is to reuse the item view:
convertView
parameter before trying to create a new instance of the item:if (convertView == null) { var inflater = LayoutInflater.From(context); convertView = inflater.Inflate( Resource.Layout.ListItemLayout, parent, false); } var firstRow = convertView.FindViewById<TextView>( Resource.Id.firstRow); firstRow.Text = person.Name;
Another way is to store references to the various subviews so that we don't have look for them each time, as follows:
private class ViewHolder : Java.Lang.Object { public ImageView Icon; public TextView FirstRow; public TextView SecondRow; }
var viewHolder = new ViewHolder { Icon = convertView.FindViewById<ImageView>( Resource.Id.icon), FirstRow = convertView.FindViewById<TextView>( Resource.Id.firstRow), SecondRow = convertView.FindViewById<TextView>( Resource.Id.secondRow) };
Tag
property:convertView.Tag = viewHolder;
var viewHolder = (ViewHolder)convertView.Tag;
viewHolder
object:viewHolder.FirstRow.Text = person.Name;
As the user is able to scroll quite fast through a list, the list needs to be able to create and update the items as fast as possible. If there is any delay, the user will notice it immediately and this makes the experience less polished.
There are two very common, and incidentally, very expensive operations that we perform for every item. These operations are inflating the views and locating the particular subviews. Every item has to be created at some point, and in order to update, the text of one item will have to find the view that will contain that text. Also, as there may be thousands of items, this executes multiple times in a second.
There are a few ways in which we can improve list and app performance, one being in the construction of the view. Instead of reconstructing the view for each item, we need to try and reuse the already existing view. An item scrolling off the screen is placed in a recycle bin in order that the item may be reused at some point. This recycle bin allows Android to limit the number of items constructed, improving both memory consumption as well as the number of CPU operations.
Android provides an easy means to reuse a view in the GetView()
method. One of the parameters passed into this method, the convertView
parameter, is an available view from the recycle bin. We can then use this view and simply update the contents with the data from the new item. As this view is actually an existing item that scrolled off the screen, we need to ensure that we reset any values that we may have set. This pattern is called Virtualization.
Another way to improve performance is to reduce the number of times we search for a view within the item. Even though we may only have a few views to update in the item, we need to remember that there may be many items, and searching for a view requires that the entire item hierarchy be searched.
We can limit the number of times we search for a view by saving the references to each view item in the item itself. We can do this by creating an object that will hold the references to all the views that we will update and then assign that object to the item. We assign the object to the item by assigning the object to the Tag
property of the item's view. We call this pattern the View Holder pattern.
There are many other performance improvements that we can do for lists. We can cache various pieces of data, such as images. We can also move expensive operations to another thread. This can be further improved by ensuring that we don't run operations unnecessarily, such as when the list is scrolling at high speed. We can also improve performance by ensuring that some of the operations are done beforehand, and the results are cached.