How does the listview work?
The ListView is where the design applies to scalability and high performance requirements. In fact, this means that the ListView has the following 2 requirements:
- Create the view as little as possible;
- Just draw and layout the child view that is visible on the screen.
Understanding the 1th is simple: creating a view from a layout XML file and displaying it 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 responded to.
The ListView solves this problem by reclaiming some invisible views, often called "Scrapview (Abandoned View)" in the Android source code. This means that developers simply need to update the content of each row without having to create a view for each individual row's layout.
To achieve the 2nd, when we swipe the screen, the ListView increases below or above the views of the current window by using the View collector, and the currently active views move to a recyclable pool. In this case, the ListView only needs to keep enough views in memory to fill the layout in the allocated space and some additional recyclable views, even when your adapter has hundreds of items to fit. It uses different methods to populate the space between rows, from the top or bottom, depending on how the window changes.
The following diagram shows intuitively what happens when you press the ListView:
By the above introduction, we are already familiar with this mechanism of the ListView, let's continue to the Tips section. As described above, when sliding, the ListView creates and reclaims many of the view dynamically, enabling the adapter GetView () to be as lightweight as possible. All the tricks are to make getview () faster through a variety of methods.
Collection of view
When the ListView needs to display a new line on the screen each time, the method of GetView () is called from its adapter. As we all know, the GetView () method has 3 parameters: the position of the row, the Convertview, and the parent viewgroup.
Parameter Convertview is the Scrapview of the previous story. Convertview is a non-null value when the ListView requires that a row of layouts be updated. So, when the Convertview value is not empty, you just need to update the content without having to re-start the layout of a new row. GetView () is generally the following form in adapter:
Public View GetView (int position, View Convertview, ViewGroup parent) { if (Convertview = = null) { Convertview = m Inflater.inflate (r.layout.your_layout, null); } TextView Text = (TextView) Convertview.findviewbyid (r.id.text); Text.settext ("Position" + Position);
View Holder How to write a template
One common operation of Android is to find an internal view in the layout file. It is usually implemented using the view method of a Findviewbyid (). This Findviewbyid () method is recursively called to find its subtree in the view tree, depending on a view ID. Although it is perfectly normal to use Findviewbyid () in a static UI layout. However, when sliding, the ListView calls its adapter in the GetView () is very frequent. Findviewbyid () may affect the performance of the ListView when it slips, especially if your row layout is complex.
Looking for an inflatable layout within the internal view is one of the most commonly used operations on Android. This is usually done by a name of Findviewbyid (see method completion). This method will recursively go through the view tree looking for a child with the given ID code. The static UI layout using Findviewbyid () is perfectly normal, but as you can see, the GetView () of the calling adapter is very frequent when scrolling in the ListView. Findviewbyid () may perceivably hit listviews, especially scrolling performance, if the layout of your line is not trivial.
The mode of View holder is to reduce the number of calls Findviewbyid () in the GetView () method in adapter. In fact, the View holder is a lightweight inner class that is used to refer directly to all internal views. After creating the view, you can store the view in each row as a label. In this way, you only need to call Findviewbyid () when you first create the layout. The following is a code example of a view holder template that uses the above method:
1 PublicView GetView (intPosition, View Convertview, ViewGroup parent) {Viewholder holder;if(Convertview = =NULL) {Convertview = Minflater.inflate (R.layout.your_layout,NULL); Holder =NewViewholder (); Holder.text = (TextView) Convertview.findviewbyid (R.id.text); Convertview.settag (holder); }Else{holder = Convertview.gettag (); } holder.text.setText ("Position" + Position);returnConvertview; }Private Static classViewholder { PublicTextView text; }
View Code
Asynchronous loading
Many times, Android apps display some multimedia content in the ListView per row, compared to slices. Using the app's built-in picture resources in Adapter GetView () is not going to be a problem because it can be stored in the Android cache. But when you want polymorphic display of content from your local disk or network, such as thumbnails, CV images, etc. 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, the ListView looks very stuttering.
An asynchronous operation on a separate thread if you want to run an IO operation on all rows or any high-load CPU limit. The trick is to be able to meet the collection behavior of the ListView. 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 for other places before the Asynctask is complete. So, once the asynchronous operation is complete, a mechanism is needed to know if the corresponding view has been reclaimed.
An easy way to achieve this is by attaching some information that identifies the view that the row is associated with. Then, when the asynchronous operation is complete, check whether the view and identity view of the target line is consistent. There are many ways to achieve this goal. Here is a very simple example of how to implement this method:
1 PublicView GetView (intPosition, View Convertview, ViewGroup parent) {Viewholder holder; ... holder.position = position;NewThumbnailtask (position, holder). Executeonexecutor (Asynctask.thread_pool_executor,NULL);returnConvertview; }Private Static classThumbnailtaskextendsAsynctask {Private intMposition;PrivateViewholder Mholder; PublicThumbnailtask (intPosition, Viewholder holder) {mposition = position; Mholder = holder; } @OverrideprotectedCursor doinbackground (Void ... arg0) {//Download bitmap here} @Override protected void OnPostExecute (bitmap bitmap) {if (mholder.posit Ion = = Mposition) {mHolder.thumbnail.setImageBitmap (bitmap); }}} private static class Viewholder {public ImageView thumbnail; public int position; }
View Code
Human Computer Interaction Knowledge
Doing so asynchronously loads a lot of resources on each line and is a necessary way for a high-performance listview. However, when sliding the screen, if you blindly in every GetView () call inside to start an asynchronous operation, 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 human-computer interaction situation, in the ListView adapter, no asynchronous operations should be triggered in each row. That is, there is no point in initiating any asynchronous operation when there is a fling (fast swipe) operation in the ListView. Once the scrolling stops or is about to stop, it's time to start to actually display the contents of each line.
I'm not going to post a code sample here because it involves too much code. Romain Guy wrote a very classic app: the shelves app, which has a good example. When the GridView stops sliding without doing anything else, it starts triggering to load the book's cover resource asynchronously. Even when you swipe, you can show what's in the cache and balance the interaction by using memory cache. That's a good idea!
Above
I highly recommend that you take a look at the Romain Guy and Adam Powell's discussion of the ListView, which covers a lot of the stuff in this article. You can look at pattrn and see how several of these techniques are used in the application.
Hopefully it's a useful reference for you in Android Development: –)
Long Luo at pm17:30.14th, @Shenzhen, China.
Original link:http://longluo.github.io/blog/20140214/some_tips_about_android_listview_performence/
Written by Frank Luo posted at Http://longluo.github.io
Several tricks to improve Android ListView performance