安卓开发手把手教你打造万能适配器,告别繁重重复代码

    大家在安卓开发过程中,经常会用到listview或者gridview,在编写代码的时候为了节约资源我们通常会采用持有者模式,即ViewHolder,如果一个工程中有多个listview,通常情况下我会写多个ViewHolder,还有多个adapter,每个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 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来存储键值对,其实在安卓中,还有一个类,叫做

SparseArray

在这个类里面有这么一段介绍,

It is intended to be more memory efficient
* than using a HashMap to map Integers to Objects

大概意思就是说它就相当于是hashmap,但是比hashmao效率更高,但是有一点要注意的是,SparseArray的键只能是integer类型!下面是我封装好了的一个ViewHolder类。

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()方法中,是不是精简了不少?

 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,然后使用的时候继承这一个通用adapter

这样说很难理解,直接看代码,下面是一个通用的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,这样就不用重写那一连串方法。继承后的代码如下:

 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());
    }
}

是不是简单了很多!!!

    原文作者:移动开发
    原文地址: https://my.oschina.net/juyao/blog/543191
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞