Several techniques for improving the performance of Android ListView

Source: Internet
Author: User
Tags static class

How does the listview work?

ListView is where the design applies to scalability and high performance requirements. In fact, this means that ListView has the following 2 requirements:

Create a view as few as possible;

Just draw and layout the child view that is visible on the screen.

Understanding the 1th is simple: creating a view and displaying it through a layout XML file is an expensive and time-consuming operation. Although the layout file has been compiled and packaged into binary form for more efficient parsing, creating a view still requires a special XML tree and instantiates all the view that needs to be answered.

ListView solves this problem by recycling some of the invisible views, often referred to as "Scrapview view" in the Android source code. This means that developers simply need to update the contents of each row without creating a view for each individual row layout.

To achieve 2nd, as we slide the screen, ListView uses the view collector to increase the views that are below or above the current window, and the currently active views are moved to a recyclable pool. In this way, ListView only needs to keep enough views in memory to populate the layout of the allocation space and some additional recyclable views, even when your adapter is fit for hundreds of items. It uses different methods to fill the space between rows, from the top or bottom, and so on, depending on how the window changes.

The following diagram is a straightforward display of what happens when you press the ListView:

Listview

With the above introduction, we are already familiar with the ListView mechanism, so let's go on to the Tip section. As described above, when sliding, ListView through the dynamic creation and recycling of a lot of view, to achieve as much as possible to adapter GetView () light. All of the techniques are to make getview () faster in a variety of ways.

Collection of view

The GetView () method is called from its adapter when ListView needs to display a new row on the screen each time. As we all know, the GetView () method has 3 parameters: the position of the row, the Convertview, and the parent viewgroup.

Parameter Convertview is to say the scrapview of the previous story. Convertview is a Non-null value when ListView requires updating a row's layout. Therefore, when the Convertview value is not empty, you simply need to update the content without having to rearrange the layout of a new line. GetView () in the adapter is generally the following form:

Public View GetView (int position, View Convertview, ViewGroup parent) {

if (Convertview = = null) {

Convertview = minflater.inflate (r.layout.your_layout, NULL);

}

TextView Text = (TextView) Convertview.findviewbyid (R.id.text);

Text.settext ("Position" + Position);

return convertview;

}

View Holder How to write a template

One of the most common operations of Android is to find an internal view in a layout file. It is usually implemented using a Findviewbyid () view method. The Findviewbyid () method in the view tree, based on a view ID, is recursively called to find its subtree. Although it is perfectly normal to use Findviewbyid () in a static UI layout. However, when sliding, ListView calls the GetView () in its adapter is very frequent. Findviewbyid () may affect the performance of ListView sliding, especially if your row layout is complex.

Finding an internal view of an inflatable layout is one of the most common operations on Android. This is usually done through a name of Findviewbyid (view method). This method recursively passes through the view tree to look for a child with a given ID code. Static UI layouts using Findviewbyid () are perfectly normal, but as you can see, the GetView () of the adapter when scrolling in ListView is very frequent. Findviewbyid () may perceivably hit listviews, especially the scrolling performance, if your line layout is extraordinary.

The View holder pattern is to reduce the number of calls to Findviewbyid () in the GetView () method in adapter. In fact, View holder is a lightweight inner class used to refer directly to all internal views. After you create the view, you can store the view in each row as a label. In this way, you simply call Findviewbyid () when you first create the layout. The following is a code example of the view holder template using the above method:

Public View GetView (int position, View Convertview, ViewGroup parent) {

Viewholder Holder;

if (Convertview = = null) {

Convertview = minflater.inflate (r.layout.your_layout, NULL);

Holder = new Viewholder ();

Holder.text = (TextView) Convertview.findviewbyid (R.id.text);

Convertview.settag (holder);

} else {

Holder = Convertview.gettag ();

}

Holder.text.setText ("Position" + Position);

return convertview;

}

private Static Class Viewholder {

public TextView text;

}

Asynchronous loading

Many times, Android apps display some multimedia content, such as pictures, in every line of ListView. The use of built-in picture resources in GetView () in adapter is not problematic because it can be stored in the Android cache. But when you want polymorphic display of content from a local disk or network, such as thumbnails, resume pictures, and so on. In this case, you may not want to load them directly in the adapter GetView (), because the IO process blocks the UI thread. If you do this, ListView will look very cotton.

In a separate thread, if you want to run all the rows of IO operations or any high load CPU limit asynchronous operations. One of the tricks is to be able to meet the ListView recycling behavior. For example, if you use Asynctask loading to load a data picture in GetView () in adapter, the picture view you are loading may be recycled to other places until Asynctask is complete. So, once the asynchronous operation is complete, a mechanism is needed to know if the corresponding view is not recycled.

An easy way to achieve this is by attaching some information that identifies the row to its associated view. Then, when the asynchronous operation completes, check that the view of the target row and the view of the identity are consistent. There are many ways to achieve this goal. Here is a simple example of how to implement this method:

public view GetView (int position, View Convertview,

ViewGroup parent) {

Viewholder Holder;

...

Holder.position = position;

New Thumbnailtask (position, holder)

. executeonexecutor (Asynctask.thread_pool_executor, NULL);

return convertview;

}

private static class Thumbnailtask extends Asynctask {

private int mposition;

Private Viewholder Mholder;

public thumbnailtask (int position, Viewholder holder) {

Mposition = position;

Mholder = holder;

}

@Override

Protected Cursor doinbackground (Void ... arg0) {

Download Bitmap Here

}

@Override

protected void OnPostExecute (Bitmap Bitmap) {

if (mholder.position = = mposition) {

MHolder.thumbnail.setImageBitmap (bitmap);

}

}

}

private Static Class Viewholder {

public ImageView thumbnail;

public int position;

}

Human-Computer Interaction knowledge

Doing a lot of resources asynchronously in every line is a necessary way for a high-performance listview to be loaded. However, when sliding the screen, if you blindly start an asynchronous operation in every GetView () call, the result is that you will waste a lot of resources. Because rows are frequently recycled, most of the returned results are discarded.

Given the actual man-machine interaction, in the ListView adapter, no asynchronous operation should be triggered in each row. That is, when there is a fling (fast sliding) operation in ListView, it does not make any sense to initiate any asynchronous operation. Once the scrolling stops or is about to stop, it's time to start displaying the contents of each line.

I will not post a code example posted here because there are too many code involved. Romain Guy wrote a classic app: Shelves app, which has a good example. When the GridView stops sliding without doing anything else, it starts to trigger to load the book's cover resource asynchronously. Even when sliding, you can display the contents of the cache by using the memory cache to balance the interactions. That's a great idea!

Above

I highly recommend that you look at the listview discussion of Romain Guy and Adam Powell, which covers a lot of this article. You can look at the pattrn and see how some of the tips in this area are applied.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.