Android打造一个通用的BaseAdapter

一般BaseAdapter的写法

package com.example.august.commonadapter;
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;
/**
 * Created by August on 16/4/9.
 */
public class MyAdapter extends BaseAdapter {
    private List mDatas;
    private Context mContext;
    public MyAdapter(List mDatas, Context mContext) {
        this.mDatas = mDatas;
        this.mContext = mContext;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(R.layout.item_text, null);
            holder = new ViewHolder();
            holder.mTextView = (TextView) convertView.findViewById(R.id.mTextView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mTextView.setText(mDatas.get(position));
        return convertView;
    }
    class ViewHolder {
        TextView mTextView;
    }
}

每次写的Adapter都写得要死,一堆都是复用的代码,下面我们就开始封装一个自己的通用Adapter,把以后的代码量尽可能减少。

findView的时间,我们会用一个ViewHolder来保存之前查找的view.以上的Adapter思路就是给Adapter传入一个经常调用的context参数还有适配的数据,其中构造器,getCount,getItem,getItemId,几乎是一样的.然后为了减少.其中我们找出每个Adapter可能不同的内容有哪些:

  • mDatas的类型 这个简单,我们使用泛型来解决
  • 解析的Layout里面的View不确定,所以ViewHolder比较难搞

其中第二个我们稍微比较麻烦一点,但是想想也挺简单的.想象ViewHolder就是一个容器,我们把View塞进去里面就好了.那我们就要用到容器了.好了知道用容器了,那么我们需要怎样去确定要使用哪个View呢?哈哈,也很简单,你会想到Map,key就是View的ID,value就是对应的View了.但我们这里推荐使用SparseArray容器,因为它的速度比常用的Map快多了,唯一确定就是键值只能是Integer型的,但是已经足够了...

ViewHolder初步优化代码

public class ViewHolder {
    private SparseArray mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray();
    }
    public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
        ViewHolder holder = null;
        if (converview == null) {
            converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
            holder = new ViewHolder(converview);
            converview.setTag(holder);
        } else {
            holder = (ViewHolder) converview.getTag();
        }
        return holder;
    }
}

这样我们就可以使用getHolder方法来去新建或取回一个ViewHolder了,有了ViewHolder还不行,我们还要获取里面的View,这里我们使用泛型去写

  public  T getView(int viewID) {
        T view = (T) mViews.get(viewID);
        if (view == null) {
            view = (T) mConvertview.findViewById(viewID);
            mViews.put(viewID, view);
        }
        return view;
    }

这样以后我们就可以获取View并且作相应操作了

GeneralParentAdapter的初步代码

下面开始编写我们GeneralParentAdapter了,因为是通用的,所以Adapter对应的Layout就需要以参数的形式传入,mDatas也需要时泛型的.

package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
 * Created by August on 16/4/9.
 */
public class GeneralParentAdapter extends BaseAdapter {
    private List mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List mDatas, Context mContext, int layoutID) {
        this.mDatas = mDatas;
        this.mContext = mContext;
        this.layoutID = layoutID;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
}

嗯,这就是那堆让人讨厌的经常反反复复去写的代码

核心方法getView

下面是Adapter的getView方法了,这里就要使用到ViewHolder了

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        
        TextView mTextView = holder.getView(R.id.mTextView);
        mTextView.setText(mDatas.get(position));
        return holder.getConverview();
    }

然后我们发现,第一行和最后一行也是可以复用的,而且我们需要返回一个converView,那么我们就在ViewHolder添加一个方法吧

public View getConvertview() {
        return this.mConvertview;
    }

迷之封装

继续,我们的Adapter就能用的,但是还不行,我们再把设置内容那里抽取出来,这才是每个Adapter真正的不同之处.现在我们把Adapter变成抽象类,并设置抽象方法setContent

  @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        setContent(holder, mDatas, position);
        return holder.getConverview();
    }
    public abstract void setContent(ViewHolder holder, List mDatas, int position);

最后我们就可以使用了

用例

ItemBean.java

package com.example.august.commonadapter;
/**
 * Created by August on 16/4/9.
 */
public class ItemBean {
    public int imgID;
    public String text;
    public ItemBean(int imgID, String text) {
        this.imgID = imgID;
        this.text = text;
    }
}

item_text.xml



    
    

调用代码

        mListView = (ListView) findViewById(R.id.mListView);
        List mDatas = new ArrayList();
        for (int i = 'A'; i < 'Z'; i++) {
            ItemBean itemBean = new ItemBean(R.drawable.pic, String.valueOf((char) i));
            mDatas.add(itemBean);
        }
        GeneralParentAdapter mAdapter = new GeneralParentAdapter(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List mDatas, int postion) {
                TextView mTextView = holder.getView(R.id.mTextView);
                mTextView.setText("666");
                ImageView mImageView = holder.getView(R.id.mImageView);
                mImageView.setImageResource(R.drawable.pic);
            }
        };
        mListView.setAdapter(mAdapter);

可以看到我们需要写的代码从一堆变成了短小精悍的几行,但还不够,我们还得上天呢 哈哈.我们再给ViewHolder设置一些通用的方法,无非是什么setText,setBitmap之类的,于是VIewHolder有了...

接口的公布

  public void setText(int viewID, String text) {
        View childView = getView(viewID);
        if (childView instanceof TextView) {
            ((TextView) childView).setText(text);
        }
    }
    public void setBitmap(int viewID, Bitmap bitmap) {
        View childView = getView(viewID);
        if (childView instanceof ImageView) {
            ((ImageView) childView).setImageBitmap(bitmap);
        }
    }

最后我们继续精简

        GeneralParentAdapter mAdapter = new GeneralParentAdapter(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List mDatas, int postion) {
                holder.setText(R.id.mTextView, mDatas.get(postion).text);
                holder.setBitmap(R.id.mImageView, BitmapFactory.decodeResource(getResources(), R.drawable.pic));
            }
        };

最后变成了两行代码,咱们就呵呵了...大家还可以根据自己需要去封装更多的方法.

整体代码

ViewHolder

package com.example.august.commonadapter;
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;
/**
 * Created by August on 16/4/9.
 */
public class ViewHolder {
    private SparseArray mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray();
    }
    public static ViewHolder getHolder(Context context, View converview, int layoutID, ViewGroup parent) {
        ViewHolder holder = null;
        if (converview == null) {
            converview = LayoutInflater.from(context).inflate(layoutID, parent, false);
            holder = new ViewHolder(converview);
            converview.setTag(holder);
        } else {
            holder = (ViewHolder) converview.getTag();
        }
        return holder;
    }
    public  T getView(int viewID) {
        T view = (T) mViews.get(viewID);
        if (view == null) {
            view = (T) mConvertview.findViewById(viewID);
            mViews.put(viewID, view);
        }
        return view;
    }
    public View getConverview() {
        return this.mConvertview;
    }
    public void setText(int viewID, String text) {
        View childView = getView(viewID);
        if (childView instanceof TextView) {
            ((TextView) childView).setText(text);
        }
    }
    public void setBitmap(int viewID, Bitmap bitmap) {
        View childView = getView(viewID);
        if (childView instanceof ImageView) {
            ((ImageView) childView).setImageBitmap(bitmap);
        }
    }
}

GeneralParentAdapter

package com.example.august.commonadapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
/**
 * Created by August on 16/4/9.
 */
public abstract class GeneralParentAdapter extends BaseAdapter {
    private List mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List mDatas, Context mContext, int layoutID) {
        this.mDatas = mDatas;
        this.mContext = mContext;
        this.layoutID = layoutID;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        holder = ViewHolder.getHolder(mContext, convertView, layoutID, parent);
        setContent(holder, mDatas, position);
        return holder.getConverview();
    }
    public abstract void setContent(ViewHolder holder, List mDatas, int position);
}

你可能感兴趣的:(Android打造一个通用的BaseAdapter)