When we use Viewholder, the Child view control objects for each item are placed in Viewholder, and when the Convertview object is first created, The child view Control object Findviewbyid of the item is instantiated and saved to the Viewholder object. Then use the Convertview Settag to set the Viewholder object to tag, when loading the ListView item can be directly removed from the tag in the reuse of Viewholder objects, You don't need to Findviewbyid to find the item's child control object again. This greatly improves performance.
However, in some cases, there is a problem with this optimization technique, for example, when we need to use a checkbox in the ListView as a result of the project:
Assuming that a ListView has 10 item, when I select the checkbox for the first item, sliding down to the previously invisible position, I find that other checkbox is also selected, which creates a bad user experience.
First, the code for this problem appears:
Layout file:
Activity_listview.xml
<?xml version= "1.0" encoding= "Utf-8"?>
<linearlayout xmlns:android= "Http://schemas.android.com/apk/res/android"
android:orientation= "vertical" android:layout_width= "match_parent"
android:layout_height= "Match_parent" >
<listview
Android:id= "@+id/listview"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent" ></ListView>
</LinearLayout>
Item_list.xml a checkbox and a TextView, set to 100DP high because there must be no display of item,listview will go to reuse view, if a screen shows all the item, then do not reply to use.
<?xml version= "1.0" encoding= "Utf-8"?>
<linearlayout xmlns:android= "Http://schemas.android.com/apk/res/android"
android:orientation= "vertical" android:layout_width= "match_parent"
android:layout_height= "Match_parent" >
<relativelayout
Android:layout_width= "Match_parent"
android:layout_height= "100DP" >
<checkbox
Android:layout_centervertical= "true"
android:layout_marginleft= "10DP"
Android:layout_width= "Wrap_content"
android:layout_height= "Wrap_content"/>
<textview
Android:id= "@+id/textview"
Android:layout_centervertical= "true"
Android:layout_centerhorizontal= "true"
Android:layout_width= "Wrap_content"
android:layout_height= "Wrap_content"/>
</RelativeLayout>
</LinearLayout>
Myadapter.java
Package cn.zmit.myapplication;
Import Android.content.Context;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.BaseAdapter;
Import Android.widget.TextView;
Import java.util.List;
/**
* Created by the Administrator on 2016/3/23.
*/
public class Myadapter extends Baseadapter {
Private list<string> List;
private context;
Public Myadapter (list<string> lists, context contexts) {
list = lists;
context = contexts;
}
@Override
public int GetCount () {
return List.size ();
}
@Override
Public Object getitem (int position) {
return List.get (position);
}
@Override
public long getitemid (int position) {
return position;
}
@Override
Public View GetView (final int position, View Convertview, ViewGroup parent) {
Viewholder Holder;
if (Convertview = = null) {
Holder = new Viewholder ();
Convertview = view.inflate (context, r.layout.item_list, null);
Holder.textview = (TextView) Convertview.findviewbyid (R.id.textview);
Convertview.settag (holder);
} else {
Holder = (viewholder) convertview.gettag ();
}
Holder.textView.setText (List.get (position));
return convertview;
}
Private class Viewholder {
TextView TextView;
}
}
Listveiwdemo.java
Package cn.zmit.myapplication;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.widget.ListAdapter;
Import Android.widget.ListView;
Import Android.widget.SimpleAdapter;
Import java.util.ArrayList;
Import java.util.List;
/**
* Created by the Administrator on 2016/3/18.
*/
public class Listviewdemo extends activity {
Private ListView ListView;
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.layout_listview);
listview= (ListView) Findviewbyid (R.id.listview);
List<string> list=new arraylist<> ();
for (int i=0;i<10;i++) {
List.add (i+ "");
}
Myadapter adapter=new Myadapter (list,this);
Listview.setadapter (adapter);
}
}
Very normal a ListView implementation process, the reason for the code is worried that beginners do not understand what I am talking about. You can copy the code or write your own to see the effect.
Now let's talk about how to solve!!!!
First, define a map,
Map<integer,view>map=new hashmap<> ();
When Convertview is null, the Convertview is added to the map after the Convertview and child control loads are completed:
Map.put (Position,convertview);
Let's think about it, this time, in front of the judge, it should be
if (Convertview = null)
Is that right? Of course not, in this way:
if (map.get (position) ==null)
In other words, as long as you this item has not been loaded, give me reload!
Then write it in the following else:
else {
Convertview=map.get (position);
Holder = (viewholder) convertview.gettag ();
}
If you have this view in map, take it out.
The GetView part of the adapter that solves the problem is:
Map<integer,view>map=new hashmap<> ();
@Override
Public View GetView (final int position, View Convertview, ViewGroup parent) {
Viewholder Holder;
if (map.get (position) ==null) {
Holder = new Viewholder ();
Convertview = view.inflate (context, r.layout.item_list, null);
Holder.textview = (TextView) Convertview.findviewbyid (R.id.textview);
Map.put (Position,convertview);
Convertview.settag (holder);
} else {
Convertview=map.get (position);
Holder = (viewholder) convertview.gettag ();
}
Holder.textView.setText (List.get (position));
return convertview;
}