你們在安卓開發過程當中,常常會用到listview或者gridview,在編寫代碼的時候爲了節約資源咱們一般會採用持有者模式,即ViewHolder,若是一個工程中有多個listview,一般狀況下我會寫多個ViewHolder,還有多個adapter,每一個adapter都要重寫一遍裏面的抽象方法,今天就教你們如何避免如此繁重的工做,可以一勞永逸。java
首先咱們先看一下傳統適配器的寫法。好比下面這段:android
package com.jy.myadapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:03 */ public class OriginAdapter extends BaseAdapter{ private List<Bean> list; private Context mcontext; private LayoutInflater minflater; public OriginAdapter(List<Bean> list, Context mcontext) { this.list = list; this.mcontext = mcontext; minflater=LayoutInflater.from(mcontext); } @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(int position, View convertView, ViewGroup parent) { ViewHolider holder; if(convertView==null){ holder=new ViewHolider(); convertView=minflater.inflate(R.layout.listitem,parent,false); holder.title= (TextView) convertView.findViewById(R.id.title); holder.dec= (TextView) convertView.findViewById(R.id.dec); holder.time= (TextView) convertView.findViewById(R.id.time); convertView.setTag(holder); }else{ holder= (ViewHolider) convertView.getTag(); } holder.title.setText(list.get(position).getTitlel()); holder.dec.setText(list.get(position).getDec()); holder.time.setText(list.get(position).getTime()); return convertView; } class ViewHolider{ TextView title; TextView dec; TextView time; } }
是否是很熟悉,當咱們在開發多個listview的時候,都要對應不一樣的viewholder,因此咱們能夠考慮將viewholder封裝起來,經過一個容器獲取對應的view,提到容器,咱們第一反應就是用map來存儲鍵值對,其實在安卓中,還有一個類,叫作dom
SparseArray
在這個類裏面有這麼一段介紹,ide
It is intended to be more memory efficient
* than using a HashMap to map Integers to Objects
大概意思就是說它就至關因而hashmap,可是比hashmao效率更高,可是有一點要注意的是,SparseArray的鍵只能是integer類型!下面是我封裝好了的一個ViewHolder類。this
package com.jy.myadapter; import android.content.Context; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:38 */ public class ViewHolder { private SparseArray<View> mViews; private int mPosition; private View mConvertView; public 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); mConvertView.setTag(this); } public static ViewHolder get(Context context,View convertview,ViewGroup parent,int layoutid,int position){ if(convertview==null){ return new ViewHolder( context, parent,layoutid, position); }else{ ViewHolder holder=(ViewHolder) convertview.getTag(); holder.mPosition=position; return holder; } } public View getmConvertView() { return mConvertView; } /** * 根據id尋找控件 * @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; } /** * 爲文本賦值 */ public void setText(int Viewid,String text){ TextView tv=getView(Viewid); tv.setText(text); } }
其其實看這段代碼很熟悉,由於他的原理和咱們以前寫的是同樣的,只不過這裏進行了封裝,仔細看的應該能夠看明白。其中settext方法是給Textview進行賦值,固然,相似的,好比imageview等等,均可以在這裏面添加對應的方法,我這裏是拿Textview舉例。封裝好了ViewHolder以後,咱們來看看怎麼使用。下面這段代碼就是使用封裝好的ViewHolder的狀況,主要看getview()方法中,是否是精簡了很多?spa
package com.jy.myadapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import org.w3c.dom.Text; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:03 */ public class MydapterWithCommonViewHolder extends BaseAdapter{ private List<Bean> list; private Context mcontext; private LayoutInflater minflater; public MydapterWithCommonViewHolder(List<Bean> list, Context mcontext) { this.list = list; this.mcontext = mcontext; minflater=LayoutInflater.from(mcontext); } @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(int position, View convertView, ViewGroup parent) { ViewHolder holder=ViewHolder.get(mcontext,convertView,parent,R.layout.listitem,position); holder.setText(R.id.title,list.get(position).getTitlel()); holder.setText(R.id.dec,list.get(position).getDec()); holder.setText(R.id.time,list.get(position).getTime()); return holder.getmConvertView(); }
只須要五行代碼。固然,這還不是最簡單的,上面我說到,除了viewholder,在多個listview的狀況下咱們要編寫多個adapter,每個adapter都要重寫多個抽象方法,那咱們是否是也能夠寫一個通用的adapter,而後使用的時候繼承這一個通用adaptercode
這樣說很難理解,直接看代碼,下面是一個通用的adapter繼承
package com.jy.myadapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 16:26 */ public abstract class CommenAdapter<T> extends BaseAdapter{ protected Context mContext; protected List<T> mData; private LayoutInflater mInflater; private int layoutid; public CommenAdapter(Context context,List<T> datas,int layoutid) { this.mContext=context; this.mData=datas; this.layoutid=layoutid; mInflater=LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public T getItem(int position) { return mData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent){ ViewHolder holder=ViewHolder.get(mContext,convertView,parent,layoutid,position); convert(holder,getItem(position)); return holder.getmConvertView(); }; public abstract void convert(ViewHolder holder,T t); }
其中,conver這個抽象方法就是用來實現每一個不一樣listview的不一樣處理邏輯,仍是拿原來的adapter爲例,繼承自這個通用adapter,這樣就不用重寫那一連串方法。繼承後的代碼以下:ci
package com.jy.myadapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import org.w3c.dom.Text; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:03 */ public class MydapterWithCommonViewHolder extends CommenAdapter<Bean>{ public MydapterWithCommonViewHolder(List<Bean> data, Context context) { super(context,data,R.layout.listitem); } @Override public void convert(ViewHolder holder, Bean bean) { holder.setText(R.id.title,bean.getTitlel()); holder.setText(R.id.dec,bean.getDec()); holder.setText(R.id.time,bean.getTime()); } }
短短几行代碼,就搞定了。資源
如今咱們來對比一下先後的代碼差距,一開始用咱們一般的寫法:
package com.jy.myadapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:03 */ public class OriginAdapter extends BaseAdapter{ private List<Bean> list; private Context mcontext; private LayoutInflater minflater; public OriginAdapter(List<Bean> list, Context mcontext) { this.list = list; this.mcontext = mcontext; minflater=LayoutInflater.from(mcontext); } @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(int position, View convertView, ViewGroup parent) { ViewHolider holder; if(convertView==null){ holder=new ViewHolider(); convertView=minflater.inflate(R.layout.listitem,parent,false); holder.title= (TextView) convertView.findViewById(R.id.title); holder.dec= (TextView) convertView.findViewById(R.id.dec); holder.time= (TextView) convertView.findViewById(R.id.time); convertView.setTag(holder); }else{ holder= (ViewHolider) convertView.getTag(); } holder.title.setText(list.get(position).getTitlel()); holder.dec.setText(list.get(position).getDec()); holder.time.setText(list.get(position).getTime()); return convertView; } class ViewHolider{ TextView title; TextView dec; TextView time; } }
再看最後咱們封裝好的寫法:
package com.jy.myadapter; import android.content.Context; import java.util.List; /** * User: juyao(1149950714@qq.com) * Date: 2015-12-12 * Time: 15:03 */ public class MydapterWithCommonViewHolder extends CommenAdapter<Bean> { public MydapterWithCommonViewHolder(List<Bean> data, Context context) { super(context, data, R.layout.listitem); } @Override public void convert(ViewHolder holder, Bean bean) { holder.setText(R.id.title, bean.getTitlel()); holder.setText(R.id.dec, bean.getDec()); holder.setText(R.id.time, bean.getTime()); } }
是否是簡單了不少!!!