Android High-speed development series to create a universal ListView GridView Adapter

Source: Internet
Author: User
Tags dota

Reprint please indicate source: http://blog.csdn.net/lmj623565791/article/details/38902805, this article from "Zhang Hongyang's Blog"

1. Overview

Believe that Android development is the most written Listview,gridview adapter, remember to develop a colleague development projects. A project down basic has been written in the ListView adapter are almost spit ~ ~ ~ Adapter generally inherit baseadapter several methods, GetView inside use Viewholder mode. In fact, most of the code is basically similar.

This blog is the first of a series of high-speed development, will take you step by step to encapsulate a common adapter.

2. Common examples

First look at one of the most common cases, everyone yimushihang a glance

1. layout file

Main layout file:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    android:layout_width=" match_parent "    android:layout_height=" Match_parent " >    <listview        android:id= "@+id/id_lv_main"        android:layout_width= "Fill_parent"        android: layout_height= "Fill_parent"/></relativelayout>

The layout file for item:

<?

XML version= "1.0" encoding= "Utf-8"? ><textview xmlns:android= "Http://schemas.android.com/apk/res/android" android:id= "@+id/id_tv_title" android:layout_width= "match_parent" android:layout_height= "50DP" android:background= "#aa111111" android:gravity= "center_vertical" android:paddingleft= "15DP " Android:textcolor= "#ffffff" android:text= "Hello" android:textsize= "20sp" android:textstyle= "bold" ></TextView>

2, Adapter

Package Com.example.zhy_baseadapterhelper;import Java.util.list;import Android.content.context;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.baseadapter;import Android.widget.textview;public class Myadapter extends Baseadapter{private Layoutinflater minflater;private Context mcontext;private list<string> mdatas;public MyAdapter (context context, List<string> mdatas) {minflater = Layoutinflater.from (context); This.mcontext = Context;this.mdatas = MDatas;} @Overridepublic int GetCount () {return mdatas.size ();} @Overridepublic Object getItem (int position) {return mdatas.get (position);} @Overridepublic long Getitemid (int position) {return position;} @Overridepublic view GetView (int position, view Convertview, ViewGroup parent) {Viewholder Viewholder = null;if (convertvi EW = = NULL) {Convertview = Minflater.inflate (R.layout.item_single_str, parent,false); viewholder = new Viewholder (); Viewholder.mtextview = (TextView) CONVERTVIEw.findviewbyid (R.id.id_tv_title); Convertview.settag (Viewholder);} Else{viewholder = (Viewholder) Convertview.gettag ();} ViewHolder.mTextView.setText (Mdatas.get (position)); return Convertview;} Private Final class Viewholder{textview Mtextview;}}

3. Activity

Package Com.example.zhy_baseadapterhelper;import Java.util.arraylist;import Java.util.arrays;import java.util.List ; Import Android.app.activity;import Android.os.bundle;import Android.widget.listview;public class MainActivity Extends Activity{private ListView mlistview;private list<string> mdatas = new Arraylist<string> ( Arrays.aslist ("Hello", "World", "Welcome"));p rivate myadapter madapter; @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); MListView = ( ListView) Findviewbyid (R.id.id_lv_main); Mlistview.setadapter (madapter = new Myadapter (this, Mdatas));}}

Above This example everyone should have written countless times, Myadapter integrated Baseadapter. Then the GetView inside uses the Viewholder mode; In general, we are writing this: for different layouts of the ListView, we will have a corresponding adapter, in adapter there will be a viewholder class to improve efficiency.

In this case the ListView will appear with the adapter class, Viewholder class; then is there any way to lower our code?

The following first take Viewholder surgery ~

3, the general Viewholder

First, the effect of Viewholder is analyzed. Bind to Convertview with Convertview.settag. Then, when Convertview, get the Convertview layout control directly from the Viewholder (Gettag) with it, eliminating the Findviewbyid time ~

In other words, each convertview is actually bound to a Viewholder object, and this viewholder is primarily used to help convertview the controls in the layout.

Then we just have to write a generic viewholder, and then for random Convertview. Provide an object so that it can be settag;

Since it's universal. Then it's impossible for this viewholder to contain member variables for various controls, because the layout of each item is different. What's the best way to do that?

Provides a container to store all the controls in each item layout, and also to be able to find them. Since the need to find, then the ListView must be not, need a key value pair to save. The key is the ID of the control. The value is a reference to the control, I believe you can immediately think of map, but we do not use map, because there is a better alternative class, is our Android provides Sparsearray this class. Similar to the map. But more than the map efficiency, just the key can only be integer.

See our Viewholder class below:

Package Com.example.zhy_baseadapterhelper;import Android.content.context;import Android.util.log;import Android.util.sparsearray;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;public class Viewholder{private final sparsearray<view> mviews;private View MConvertView ;p rivate Viewholder (context context, viewgroup parent, int layoutid,int position) {this.mviews = new sparsearray<view& gt; (); Mconvertview = Layoutinflater.from (context). Inflate (LayoutID, parent,false);//settagmconvertview.settag ( this);}  /** * Got a Viewholder Object * @param context * @param convertview * @param parent * @param layoutid * @param position * @return */public static Viewholder Get (context context, View convertview,viewgroup parent, int layoutid, int position) {if (conver TView = = null) {return new Viewholder (context, parent, layoutid, position);} Return (Viewholder) Convertview.gettag ();} /** * Gets the control for the control by its ID. If not, add views * @param viewId * @return */public <t extends VIEW&GT T getView (int viewId) {View view = Mviews.get (ViewId), if (view = = null) {view = Mconvertview.findviewbyid (viewId); Mviews.put (viewId, view);} Return (T) view;} Public View Getconvertview () {return mconvertview;}}


Unlike traditional viewholder, we use a sparsearray<view> to store all of the controls that are used for convertview, and when these controls are needed, they are obtained by GetView (ID);

Here's a look at the myadapter using the Viewholder.

@Overridepublic view GetView (int position, view Convertview, ViewGroup parent) {//instantiate a viewholderviewholder Viewholder = Viewholder.get (Mcontext, Convertview, parent,r.layout.item_single_str, position);//GetView get control TextView TV = Viewholder.getview (r.id.id_tv_title);//Use Tv.settext (mdatas.get (position)); return Viewholder.getconvertview ();}

Just look at GetView, the other methods are the same; first call the Viewholder get method. Suppose Convertview is a viewholder instance of null,new. By using Minflater.inflate to load the layout, and then new a sparsearray for storing the view, the last Settag (this);

Assuming that there is a direct gettag

Finally, the control is obtained by GetView (ID), assuming the presence is returned directly. Otherwise call Findviewbyid, return store, return.

Well, a general-purpose Viewholder is written. After a project dozens of adapter a viewholder directly hold the audience ~ ~ Everyone can save some time to fight a small landlord ~ ~

4, build the general adapter

With the general Viewholder everyone must not be satisfied, how also to save the time of DotA, people in the tower in ~ ~

Here's how to build a passing adapter called Commonadapter

Continue the analysis. Adapter generally need to maintain a list object that stores a collection of beans. Different ListView. Beans must be different, this commonadapter must support generics, internal maintenance of a list<t> solve our problems;

So we initially built our commonadapter.

Package Com.example.zhy_baseadapterhelper;import Java.util.list;import Android.content.context;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.baseadapter;import Android.widget.textview;public abstract class Commonadapter<t> extends baseadapter{protected layoutinflater minflater;protected Context mcontext;protected list<t> mDatas;public Commonadapter (context context, list<t> Mdatas) {minflater = Layoutinflater.from (context); This.mcontext = Context ; this.mdatas = Mdatas;} @Overridepublic int GetCount () {return mdatas.size ();} @Overridepublic Object getItem (int position) {return mdatas.get (position);} @Overridepublic long Getitemid (int position) {return position;}}
Our commonadapter is still an abstract class, in addition to GetView we have implemented other code, in this case, in the use of our adapter only to achieve a getview. Then GetView inside again use we build through Viewholder is not feel good ~

And now our myadapter is this:

Package Com.example.zhy_baseadapterhelper;import Java.util.list;import Android.content.context;import Android.view.view;import Android.view.viewgroup;import Android.widget.textview;public class MyAdapter<T> Extends Commonadapter<t>{public myadapter (context context, list<t> Mdatas) {Super (context, Mdatas);} @Overridepublic 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 ();}}

All the code added up to 10 rows or so, is not refreshing cool ~ ~ Wait. I'll go to the DotA first ~

But are we just so satisfied? Obviously it can be simplified.

5. Further casting

Note The code inside our GetView, although there are only 4 lines. But I think the whole adapter.

The first line (Viewholder Viewholder = Getviewholder (position, convertview,parent);) and

Last line: Return Viewholder.getconvertview (); it must be the same.

So we can do this: we write the first and the last line to die, the middle of the change of the part extracted, this is not OO design principles.

Now Commonadapter is this:

Package Com.example.zhy_baseadapterhelper;import Java.util.list;import Android.content.context;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.baseadapter;public abstract class Commonadapter<t> extends baseadapter{protected LayoutInflater minflater;protected Context mcontext;protected list<t> mdatas;protected final int mitemlayoutid;public Commonadapter (context context, list<t> mdatas, int itemlayoutid) {This.mcontext = Context;this.minflater = Layoutinflater.from (mcontext); this.mdatas = Mdatas;this.mitemlayoutid = Itemlayoutid;} @Overridepublic int GetCount () {return mdatas.size ();} @Overridepublic T getItem (int position) {return mdatas.get (position);} @Overridepublic long Getitemid (int position) {return position;} @Overridepublic view GetView (int position, view Convertview, ViewGroup parent) {final Viewholder Viewholder = Getviewholde R (position, convertview,parent); convert (Viewholder, GetItem (position)); return VIewholder.getconvertview ();} public abstract void Convert (Viewholder helper, T Item);p rivate viewholder getviewholder (int position, View convertview,v Iewgroup parent) {return Viewholder.get (Mcontext, Convertview, parent, mitemlayoutid,position);}}

Released a convert method, and also the Viewholder and this item for the Bean object to the outgoing, now the convert method inside what need to do?

The view is found by Viewholder, and the value is set by item;

Now I think the code is simplified so that I don't have to write a single adapter, directly mainactivity anonymous inner class walk ~

@Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview ( R.layout.activity_main) Mlistview = (ListView) Findviewbyid (r.id.id_lv_main);//Set adapter Mlistview.setadapter (MAdapter = New Commonadapter<string> (Getapplicationcontext (), Mdatas, r.layout.item_single_str) {@Overridepublic void Convert (viewholder C, String item) {TextView view = Viewholder.getview (R.id.id_tv_title); View.settext (item);}});

It's good to see how it works.

Do you think it would be easier? I think it's going to improve.

6, adapter last seal Demon

We need this in Convertview now:

@Override
public void convert (Viewholder viewholder, String Item)
{
TextView view = Viewholder.getview (R.id.id_tv_title);
View.settext (item);
}

We think about it, in fact, the layout of the view is often used in so many ways: Imageview,textview,button,checkbox and so on;

Then I think Viewholder can also encapsulate some of the methods that are used frequently. For example SetText (id,string); Setimageresource (ViewId, resId). Setimagebitmap (ViewId, bitmap);

So now Viewholder is:

Package Com.example.zhy_baseadapterhelper;import Android.content.context;import Android.graphics.bitmap;import Android.util.sparsearray;import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.imageview;import Android.widget.textview;import Com.example.zhy_ Baseadapterhelper. Imageloader.type;public class Viewholder{private final sparsearray<view> mviews;private int mPosition;private View mconvertview;private Viewholder (context context, viewgroup parent, int layoutid,int position) {this.mposition = Position;this.mviews = new sparsearray<view> (); Mconvertview = Layoutinflater.from (context). Inflate (LayoutId, Parent,false);//Settagmconvertview.settag (this);} /** * Got a Viewholder Object * * @param context * @param convertview * @param parent * @param layoutid * @param position * @ret Urn */public static Viewholder get (context context, View convertview,viewgroup parent, int layoutid, int position) {if (con Vertview = = null) {return newViewholder (context, parent, layoutid, position);} Return (Viewholder) Convertview.gettag ();} Public View Getconvertview () {return mconvertview;} /** * Gets the control for the control by its ID. If not, add views * * @param viewId * @return */public <t extends view> T getView (int viewId) {View view = Mviews.get (vie WID); if (view = = null) {view = Mconvertview.findviewbyid (viewId); Mviews.put (viewId, view);} Return (T) view;} /** * Set string for TextView * * @param viewId * @param text * @return */public viewholder setText (int viewId, string text) {TEXTV Iew view = GetView (viewId); View.settext (text); return this;}  /** * Set Picture for ImageView * * @param viewId * @param drawableid * @return */public viewholder setimageresource (int viewId, int Drawableid) {ImageView view = GetView (viewId); View.setimageresource (Drawableid); return this; /** * Set Picture for ImageView * * @param viewId * @param drawableid * @return */public viewholder setimagebitmap (int viewId, BITMA P BM) {ImageView view = GetView (viewId); View.setimagebitmap (BM); return this;} /** * for ImagevieW Set Picture * * @param viewId * @param drawableid * @return */public viewholder setimagebyurl (int viewId, String url) {imageload Er.getinstance (3, Type.lifo). LoadImage (URL, (ImageView) GetView (viewId)); return this; public int getPosition () {return mposition;}}

Today's mainactivity only need to write this:

Madapter = new Commonadapter<string> (Getapplicationcontext (), R.layout.item_single_str, MDatas) {@ overrideprotected void Convert (Viewholder viewholder, String Item) {Viewholder.settext (R.id.id_tv_title, item);}};

Convertview inside just a line of code ~ ~ ~

Well, to this our general adapter has been a step by step casting completed ~ How, after writing the project save time is not able to accompany me to learn DotA (ps:11 nickname: Blood 404) ~ ~

Note: About Viewholder inside of the Settext,setimageresource this kind of method, we can in the process of use constantly intact. Today I find this control can set the value, OK, put it in, time is long. The basic is intact. And that Imageloader is one of my blog posts, and you can use UIL. Volley or write a picture loader yourself.

7. Practice

Said so much, still have to take out to let our practice test test, by the way a few sets of pictures, as the saying goes, no picture is not positive phase.

1. The diagram of our example code is this:

The code for adapter and Viewholder is this:

Set Adapter Mlistview.setadapter (Madapter = new commonadapter<string> (Getapplicationcontext (), MDatas, R.LAYOUT.ITEM_SINGLE_STR) {@Overridepublic void convert (Viewholder helper, String Item) {Helper.settext (r.id.id_tv_ Title,item);});

Ouch, I'm not just going to stick a line;

2, to a complex point of the layout

<?xml version= "1.0" encoding= "Utf-8"? ><relativelayout xmlns:android= "http://schemas.android.com/apk/res/ Android "    android:layout_width=" match_parent "    android:layout_height=" Wrap_content "    android: Background= "#ffffff"    android:orientation= "vertical"    android:padding= "10DP" >    <textview        Android:id= "@+id/tv_title"        android:layout_width= "match_parent"        android:layout_height= "Wrap_content"        android:singleline= "true"        android:text= "Red wallet"        android:textsize= "16sp"        android:textcolor= "# 444444 ">    </TextView>    <textview        android:id=" @+id/tv_describe "        android:layout_ Width= "Match_parent"

Android High-speed development series to create a universal ListView GridView Adapter

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.