安卓開發手把手教你打造萬能適配器,告別繁重重複代碼

    你們在安卓開發過程當中,常常會用到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());
    }
}

是否是簡單了不少!!!

相關文章
相關標籤/搜索