Principle Analysis and Solution of control display repetition/error during Android ListView Sliding Process
Preface:
To improve the ListView performance, the most common method is to add a ViewHolder static class.
Although the performance is greatly improved, the content of the Item control is displayed repeatedly or in disorder.
Analyze and solve the following two problems
1. Display errors caused by uninitialized control data.
Ii. Display errors and duplicates due to Asynchronous Network loading.
The following is a brief analysis of the ListView cache mechanism. The entire article uses models as an example.
(Picture to http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html)
Process Analysis:
1. when getView () obtains the items of each row and slides down, if Item1 has completely slipped out of the screen and there is no View corresponding to Item1 in the cache, it is put into the cache.
2. The Item8 to be slide will first determine whether there are available items in the cache. If so, the corresponding View in the cache will be taken for reuse.
3. The ListView displays the sliding Item8 and refreshes all items in the ListView (getView.
So the question is...
1. Display Error Caused by uninitialized Control Data
When Item1 is reused during the getView () process of Item8, all the initial values of Item8 are the values of Item1. If no value is assigned to any controls in Item8, the displayed content will be exactly the same as item1.
Instance code:
Public View getView (int position, View convertView, ViewGroup parent) {ViewHolder viewHolder; if (convertView = null) {viewHolder = new ViewHolder (); convertView = layoutInflater. inflate (R. layout. listview, parent, false); viewHolder. tvTitle = (TextView) convertView. findViewById (R. id. TV _title); convertView. setTag (viewHolder);} else {viewHolder = (ViewHolder) convertView. getTag ();} // All items above Item7 are not assigned the if (position <= 7) {viewHolder. tvTitle. setText (title + String. valueOf (position);} return convertView ;}
The running effect is as follows:
We found that the View in the ListView cache mechanism is reused because the value is not re-assigned after Item7.
Solution:
This problem is better solved by assigning values to all controls of each Item, so that the initial data in the cache is overwritten.
The Code is as follows:
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null){ viewHolder = new ViewHolder(); convertView = layoutInflater.inflate(R.layout.listview,parent,false); viewHolder.tvTitle = (TextView)convertView.findViewById(R.id.tv_title); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder)convertView.getTag(); } //if(position <= 7){ viewHolder.tvTitle.setText(title + String.valueOf(position)); //} return convertView; }
:
Solve the problem.
Ii. Display errors and duplicates due to Asynchronous Network loading.
For example, the Item has the like function. It is lazy and has not been used as an example. So come and come with me.
Let's assume that the user clicks the like button of Item1 (at this time, the server is requested...). When the server is requested, you suddenly slide down.
As shown in, Item1 is put into the cache, while Item8 reuse the View of Item1. In this case, the Item1 thumb up request is successful and the like status is displayed. In this case, Item8 is a reusable View of Item1, so the Item8 like button will be inexplicably lit up. Then I got circled and began to think about it. Who? Who? Who are you? This is also the cause of image loading errors. (Picture solution http://www.trinea.cn/android/android-listview-display-error-image-when-scroll)
Three solutions:
1. This problem does not exist if ViewHolder is not used. Every time an Item slides in, the control is re-created. But can you use it? Okay, use it if you are willing to use it;
2. HashMap to mark the corresponding View (HashMap ), You can also use it if there are very few items. If there are too many items, there will be as many key-value pairs as there are views, so the memory will grow larger and less scientific;
3. Tag, final solution.
The following describes how to solve the above problem through Tag.
First paste the pure-handed code
Public View getView (int position, View convertView, ViewGroup parent) {ViewHolder viewHolder; if (convertView = null) {viewHolder = new ViewHolder (); convertView = layoutInflater. inflate (R. layout. listview, parent, false); viewHolder. btnZ = (Button) convertView. findViewById (R. id. button); convertView. setTag (viewHolder);} else {viewHolder = (ViewHolder) convertView. getTag ();} viewHolder. btnZ. setTag (position); viewHolder. btnZ. setText (step on); viewHolder. btnZ. setOnClickListener (new View. onClickListener () {@ Override public void onClick (View v) {if (// server access successful) {if (int) viewHolder. btnZ. getTag () = position) {// asynchronously display viewHolder. btnZ. setText (like); Action }}}); return convertView ;}
Solve the problem.
For the above Code, let's talk about the role of Tag in ListView.
After the user clicks the like Button on Item1, The Item1 Button enters the request server, and the user slides down. After Item1 slides out, the View is reused to Item8 and displayed, at this time, Item1 and Item8 control the same View at the same time, but Item8 overwrites the reused View according to its data and overwrites the viewHolder on The View. the btnZ tag is remarked as its tag. Assume that the Item1 request has just succeeded and the control needs to be refreshed. However, according to the above Code... if you want to display the status after successful loading of Item, you need to judge the tag and position. At this time, Item1 executes viewHolder. btnZ. the getTag () method finds that the tag is already 7 (Item8), and the position of Item1 is 0. Therefore, they were rejected by others ~
Therefore, we can use this comparison method to easily avoid the error of Item display.
Summary:
In the case of asynchronous loading, slide the ListView, the Item is reused, and the previous Item has just been asynchronously loaded successfully.
GetTag () obtains the "correct Item mark" currently displayed, and position is probably the Item before the View.
If you understand the above principles, we believe that no matter whether it is an image or a button, you can avoid display errors.