After the previous optimization layout, let’s talk about how to build a general adapter. So what can a general adapter do? It's very simple, reduce our writing of the code, and start to upload the code below.
public class MyAdapter extends BaseAdapter { private List<Student> data; public MyAdapter(List<Student> data) { = data; } @Override public int getCount() { return data == null ? 0 : (); } @Override public Object getItem(int position) { return (position); } @Override public long getItemId(int position) { return position; } /** * * @param position * @param convertView * @param parent * @return */ @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ //Analysis of layout convertView = (()).inflate(.list_item,null); //Create ViewHolder Holding Class holder = new ViewHolder(); //Save the object of each control to the holding class = (TextView)(.mTv1); = (TextView)(.mTv2); //Set this hold class object in each convertView object (holder); } //Every time you need to use this holder class, you will get it holder = (ViewHolder)(); //Then you can directly use the controls in this class to operate on the controls without repeatedly searching the findViewById ((position).getName()); ((position).getSex()); return convertView; } /** * Save all current control ids through this class */ static class ViewHolder{ TextView tvName; TextView tvSex; } }
In the above code, let's first look at which code formats or forms are used repeatedly. First of all, it is not difficult to see whether the three methods of public int getCount(), public long getItemId(int position) and public long getItemId(int position) are implemented every time? Therefore, we can extract these codes first and put them in MyBaseAdapter. Since the important part of each time is to implement the getView method, we don't need to write this method here. Just set MyBaseAdapter as an abstract class. However, the class that implements the getView is needed to inherit it. Therefore, MyAdapter can inherit MyBaseAdapter and then implement the getView method.
public abstract class MyBaseAdapter extends BaseAdapter { protected List<Student> data; public MyBaseAdapter(List<Student> data){ = data; } @Override public int getCount() { return data == null ? 0 : (); } @Override public Object getItem(int position) { return (position); } @Override public long getItemId(int position) { return position; } }
public class MyAdapter extends MyBaseAdapter { public MyAdapter(List<Student> data) { super(data); = data; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ convertView = (()).inflate(.list_item,null); holder = new ViewHolder(); = (TextView)(.mTv1); = (TextView)(.mTv2); (holder); } holder = (ViewHolder)(); ((position).getName()); ((position).getSex()); return convertView; } static class ViewHolder{ TextView tvName; TextView tvSex; } }
In this way, you only need to inherit MyBaseAdapter every time you customize it, but the same sentence is that there is no optimal, only better, so we have to continue to optimize and encapsulate it. So, let’s look at the above getView method, which other codes are the codes we often reuse? In fact, you will find that we need to operate the same code every time:
ViewHolder holder = null; if(convertView == null){ convertView = (()).inflate(.list_item,null); holder = new ViewHolder(); = (TextView)(.mTv1); = (TextView)(.mTv2); (holder); } holder = (ViewHolder)(); ((position).getName()); ((position).getSex()); return convertView; }
We can understand this code again. First, we need to create a holder holder object every time and set it to the corresponding converView setTag. Then, every time we need to get the hoder object and operate the controls in the hoder object. For the above code, we can directly simplify it to the following steps
holder = get holder //Every time you get the corresponding holder object
tv = () //Get the corresponding id of each control
3. () //Operate the control
4. return view //Return view
Let’s start writing a general ViewHolder general class to optimize our implementation. The code is as follows:
public class ViewHolder { // The current location being clicked private int position; //Use a map collection to save the id of each control. This SparseArray is a more efficient one provided by Android than map usage // Collection, but the limitation is that the key can only be of int type, so when the key value pair involves that the key is of int type, you can give priority to using this collection private SparseArray<View> array; //Reused layout private View convertView; //Context private Context context; //The layout resource id of the parsed private int layout; public ViewHolder(){ } //The method with three constructs is used. Here, the constructor is private to prevent the outside world from creating it. You can create objects through your own static methods. private ViewHolder(ViewGroup parent,int position,int layout){ = position; = (); //Every time an object is created, the layout is parsed convertView = (()).inflate(layout,null); //Then save the object to the setTag corresponding to convertView to facilitate the acquisition every time (this); array = new SparseArray<>(); } //Through this method, you can create a ViewHolder object public static ViewHolder getHolder(View convertView, ViewGroup parent, int position,int layout){ //Every time I judge whether the converView is empty, if it is empty, it will directly return the created object if(convertView == null){ return new ViewHolder(parent,position,layout); }else{ //The case is not empty, just like the code above, each time we get the corresponding ViewHolder object through the reused control. ViewHolder holder = (ViewHolder)(); //The position of the lower subscript must be updated here. Although the objects are the same, we have to update the existing position every time. = position; //Return the already created holder object return holder; } } /** * This method is to get the corresponding control through the control id */ public <T extends View> T getView(int viewId){ //Every time, use the viewId key to get the corresponding control View view = (viewId); //If it is empty, it means that the control has not been stored in the collection. if(view == null){ //First go to get the control id through the convertView view = (viewId); //Save to the collection so that it can be directly retrieved next time (viewId,view); } //Return the View subclass control, the convenience of using generics does not require casting return (T)view; } //Get the converView layout public View getConvertView(){ return convertView; }
Through the above code, we have encapsulated a general ViewHolder class. The following is a simpler code:
public class MyAdapter extends MyBaseAdapter { public MyAdapter(List<Student> data) { super(data); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = (convertView,parent,position, .list_item); TextView tvName = (.mTv1); TextView tvSex = (.mTv2); ((position).getName()); ((position).getSex()); return (); } }
Okay, the above code is not simpler. In fact, we are just encapsulating the ViewHolder class here, and there are more general ones waiting for us to encapsulate. What we need to encapsulate next time is how to encapsulate the code in the getView again, which has achieved better results.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.