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<String> mDatas;
    private Context mContext;
    public MyAdapter(List<String> 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<View> mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray<View>();
    }
    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 extends View> 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<T> extends BaseAdapter {
    private List<T> mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List<T> 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<T> 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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/mImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/mTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:textSize="18sp" />
</LinearLayout>

调用代码

        mListView = (ListView) findViewById(R.id.mListView);
        List<ItemBean> mDatas = new ArrayList<ItemBean>();
        for (int i = 'A'; i < 'Z'; i++) {
            ItemBean itemBean = new ItemBean(R.drawable.pic, String.valueOf((char) i));
            mDatas.add(itemBean);
        }
        GeneralParentAdapter<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List<ItemBean> 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<ItemBean> mAdapter = new GeneralParentAdapter<ItemBean>(mDatas, MainActivity.this, R.layout.item_text) {
            @Override
            public void setContent(ViewHolder holder, List<ItemBean> 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<View> mViews;
    private View mConvertview;
    public ViewHolder(View converview) {
        this.mConvertview = converview;
        mViews = new SparseArray<View>();
    }
    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 extends View> 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<T> extends BaseAdapter {
    private List<T> mDatas;
    private Context mContext;
    private int layoutID;
    private ViewHolder holder;
    public GeneralParentAdapter(List<T> 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<T> mDatas, int position);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,504评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,898评论 1 300
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,218评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,322评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,693评论 3 290
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,812评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,010评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,747评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,476评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,700评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,190评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,541评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,206评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,129评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,903评论 0 199
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,894评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,748评论 2 274

推荐阅读更多精彩内容