The generic Adapter and ListView do not load image encapsulation during scrolling,

Source: Internet
Author: User

The generic Adapter and ListView do not load image encapsulation during scrolling,

This article is original, reproduced please indicate the link: http://blog.kymjs.com/

Writing an Adapter in Android development is a very troublesome task. It is boring and repetitive, but it has to be done. Generally, the Adapter inherits several methods of BaseAdapter rewriting. In getView, ViewHolder is used for storage. In fact, most of the Code is similar. This article will take you to encapsulate the Adapter into a universal Adapter.

For the complete Demo in this article, you can refer to the instances encapsulated in KJFrameForAndroid development framework 2.2, KJAdapter and AdapterHolder.
Next, let's go to the text. The following code should be the most visible:

public class EmojiGridAdapter extends BaseAdapter {    private List<Emojicon> datas;    private final Context cxt;    public EmojiGridAdapter(Context cxt, List<Emojicon> datas) {        this.cxt = cxt;        if (datas == null) {            datas = new ArrayList<Emojicon>(0);        }        this.datas = datas;    }    public void refresh(List<Emojicon> datas) {        if (datas == null) {            datas = new ArrayList<Emojicon>(0);        }        this.datas = datas;        notifyDataSetChanged();    }    @Override    public int getCount() {        return datas.size();    }    @Override    public Object getItem(int position) {        return datas.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    private static class ViewHolder {        ImageView image;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        if (convertView == null) {            holder = new ViewHolder();            ......            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        holder.image.setImageResource(datas.get(position).getResId());        return convertView;    }}


Preliminary Extraction

The four methods of BaseAdapter must be written, but the first three methods are the same. Therefore, you can use generics to write a base class and encapsulate the data into the base class, you only need to input the constructor.

public class KJBaseAdapter<T> extends BaseAdapter {List<T> datas; KJBaseAdapter(Context cxt,List<T> datas){......}@Override    public int getCount() {        return datas.size();    }    @Override    public Object getItem(int position) {        return datas.get(position);    }    @Override    public long getItemId(int position) {        return position;    }}

Then there is our only getView () method that requires brains. First, we need to judge whether converView is empty, then load the item layout, then initialize the ViewHolder control one by one, and then store the holder through the tag, finally, set the View display.
As you know, ViewHolder must be a static class containing the item sub-control. Then we simply put all the sub-Controls of item into ViewHolder. However, since we want to use them universally, items are definitely not fixed, in this case, ViewHolder cannot be written in the form of the attribute above.
Here we use a key-value pair to store all the Map <id, view> controls, so that we can find the corresponding child View directly by id when needed.

MViews = new Map <Integaer, View> ();/*** get the corresponding control through the control Id, if not, add views ** @ param viewId * @ return */public <T extends View> T getView (int viewId) {View view = mViews. get (viewId); if (view = null) {view = mConvertView. findViewById (viewId); mViews. put (viewId, view);} return (T) view ;}

Encapsulate ViewHolder

Only getView is used. All other methods are the same. First, call the get method of ViewHolder. If convertView is null, a new ViewHolder instance is called by using mInflater.
Inflate loads the layout, and then a new HashMap is used to store the View, and the last setTag (this); if so, the getTag directly obtains the control through getView (id). If yes, the system returns the result directly, otherwise, the findViewById is called.

This is the final encapsulated ViewHolder.

Public class AdapterHolder {private final Map <Integer, View> mViews; private final int mPosition; private final View mConvertView; private AdapterHolder (ViewGroup parent, int layoutId, int position) {this. mPosition = position; this. mViews = new HashMap <Integer, View> (); mConvertView = LayoutInflater. from (parent. getContext ()). inflate (layoutId, parent, false); // setTag mConvertView. setTag (this);}/*** get a ViewHolder object */public static AdapterHolder get (View convertView, ViewGroup parent, int layoutId, int position) {if (convertView = null) {return new AdapterHolder (parent, layoutId, position);} else {return (AdapterHolder) convertView. getTag () ;}}/*** get the corresponding control using the control Id, if not, add views ** @ param viewId * @ return */public <T extends View> T getView (int viewId) {View view = mViews. get (viewId); if (view = null) {view = mConvertView. findViewById (viewId); mViews. put (viewId, view) ;}return (T) view ;}}

Combined with the previous base class, our Adapter becomes like this

public class EmojiGridAdapter<T> extends KJBaseAdapter<T> {        @Override      public View getView(int position, View convertView, ViewGroup parent){          ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent,                  R.layout.item_single_str, position);          TextView mTitle = viewHolder.getView(R.id.id_tv_title);          mTitle.setText((String) mDatas.get(position));          return viewHolder.getConvertView();      }  }

Final Encapsulation

After careful observation, the ViewHolder. get () method of the first line and the return Method of the last line certainly remain unchanged, and further encapsulation is decisive.
You can just extract the variable part of getView-locate the View through ViewHolder and set the value through Item; this part is written separately. Then we write a method called convert () to do this. So far, the code is simplified, and the rest does not need to write an Adapter separately. It is sufficient to directly use the anonymous internal class of the Activity.

Protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); mListView = (ListView) findViewById (R. id. id_lv_main); // sets the adapter mListView. setAdapter (mAdapter = new CommonAdapter <String> (getApplicationContext (), mDatas, R. layout. item_single_str) {@ Override public void convert (ViewHolder c, String item) {TextView view = viewHolder. getView (R. id. id_ TV _title); view. setText (item );}});}

Final Optimization

Now let's compare the encapsulation in KJFrameForAndroid. We can see that SparseArray is used to replace our Map. SparseArray is actually a class with two arrays, and the first array is an int []. it is used as the key, and the second is the generic type. View [] is used here. It is a class recommended by google to replace int as the Map set of the key.

Another detail is the encapsulation in KJFrameForAndroid. An absListView attribute is added and a rolling listener is set, in this way, you can easily implement functions such as not loading images during listview scrolling in the base class.

Finally, we encapsulate the subsequent code: You can directly view the KJAdapter and AdapterHolder classes. For more information about the usage, see KJBlog. For example:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.