The ListView control is very difficult to use, because it has a lot of detail to optimize, and the operational efficiency is very important. Our ListView is currently running at a low efficiency because the layout is reloaded once each time in the Fruitadapter GetView () method, which becomes a bottleneck for performance when the ListView is scrolling fast.
Carefully observed, the GetView () method also has a Convertview parameter, which is used to cache the previously loaded layout so that it can be reused later. Modify the code in the Fruitadapter as follows:
public class Fruitadapter extends Arrayadapter<fruit> {
......
@Override
Public View GetView (int position, View Convertview, ViewGroup parent) {Fruit Fruit = GetItem (position);
View view;
if (Convertview = = null) {
View = Layoutinflater.from (GetContext ()). Inflate (resourceId, NULL);
} else {
view = Convertview;
}
ImageView fruitimage = (ImageView) View.findviewbyid (r.id.fruit_image); TextView fruitname = (TextView) View.findviewbyid (r.id.fruit_name); Fruitimage.setimageresource (Fruit.getimageid ()) ; Fruitname.settext (Fruit.getname ());
return view;
}
}
As you can see, we now judge in the GetView () method that if Convertview is empty, the layout is loaded using Layoutinflater, and if not empty, the Convertview is reused directly. This greatly improves the efficiency of the ListView, and can also show better performance in fast scrolling.
However, currently our code can continue to optimize, although it is no longer repeated to load the layout, but each time in the GetView () method will call the View's Findviewbyid () method to get the instance of the control. We can use a viewholder to optimize this part of the performance and modify the code in the Fruitadapter as follows:
public class Fruitadapter extends Arrayadapter<fruit> {
......
@Override
Public View GetView (int position, View Convertview, ViewGroup parent) {fruitfruit = GetItem (position);
View view;
Viewholder Viewholder;
if (Convertview = = null) {
View = Layoutinflater.from (GetContext ()). Inflate (resourceId, NULL);
Viewholder = new Viewholder ();
Viewholder.fruitimage = (ImageView) View.findviewbyid
(R.id.fruit_image);
Viewholder.fruitname = (TextView) View.findviewbyid
(R.id.fruit_name);
View.settag (Viewholder);// store viewholder in view
} else {
view = Convertview;
Viewholder = (viewholder) view.gettag ();// retrieve Viewholder
}viewholder.fruitimage.setimageresource (Fruit.getimageid ()); ViewHolder.fruitName.setText (Fruit.getname ());
return view;
}
Class Viewholder {ImageView fruitimage; TextView Fruitname;
}
}
We have added an internal class Viewholder to cache instances of the control. When Convertview is empty, create a Viewholder object and store the instance of the control in Viewholder, then call the view's Settag () method, storing the Viewholder object in the view. When Convertview is not empty, call the View's Gettag () method to remove the Viewholder. So that the instances of all the controls are in Viewholder, it is not necessary to get the control instance through the Findviewbyid () method every time.
With this two-step optimization, our ListView is already running at a very good rate.
3.5.4 ListView Click events
After all, the ListView's scrolling only satisfies our visual effect, but if the child in the ListView cannot be clicked, the control has no practical purpose. So in this section we'll learn how the ListView can respond to a user's click events.
Modify the code in the mainactivity as follows:
public class Mainactivity extends Activity {
Private list<fruit> fruitlist = newarraylist<fruit> ();
@Override
Protected voidoncreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.activity_main); Initfruits ();
Fruitadapter adapter = Newfruitadapter (Mainactivity.this, R.layout.fruit_item, fruitlist);
ListView ListView = (ListView) Findviewbyid (R.id.list_view); Listview.setadapter (adapter); Listview.setonitemclicklistener (new Onitemclicklistener () {
@Override
Public Voidonitemclick (adapterview<?> parent, view view, int position, long ID) {
Fruit Fruit = fruitlist.get (position); Toast.maketext (Mainactivity.this, Fruit.getname (),
Toast.length_short). Show ();
}
});
}
......
}
As you can see, we used the Setonitemclicklistener () method to register a listener for the ListView, and the Onitemclick () method is called back when the user clicks on any of the subkeys in the ListView. In this method, the position parameter can be used to determine which subkey the user clicked on, then obtain the corresponding fruit and display the name of the fruit by Toast.
Rerun the program and click on the watermelon, effect 3.31 shown.
Figure 3.31
Android: Improves the efficiency of the ListView operation