Android BaseAdapter 封装总结(二)

Android BaseAdapter 封装总结(二)

上篇文章总结了关于BaseViewHolder的封装,这篇文章总结关于模块组装Adapter的封装

多种类型的viewType,通过模块代理(Delegate)组装

首先,我们了解一下什么模块组装Adapter目的。

我们在写不同的界面的时候,往往会针对不同的界面展示,编写不同的Adapter。当某些界面具有相同元素的时候,能不能不重写Adapter,而是通过组装(add)的方式,将我们之前写好的Adapter通过AdapterDelegateManager添加(add)进来。这就是我们模块组装Adapter目的。

先打造一个AdapterDelegateManager,来代理执行BaseAdapter中的抽象方法,主要为一下三个方法:

@Override
public int getItemViewType(int position){
      return 0;
}

@Override
public int getViewTypeCount() {
    return 1;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    return null;
}

打造后的AdapterDelegateManager如下:

/**
 * @param <T> adapter 数据源
 */
public class AdapterDelegateManage<T> {

    private SparseArrayCompat<AdapterDelegate<T>> delegates = new SparseArrayCompat<>();

    public AdapterDelegateManage<T> addDelegate(@NonNull AdapterDelegate<T> delegate) {

        int viewType = delegates.size();
        if (delegates.get(viewType) != null) {
            viewType++;
        }
        addDelegate(viewType, false, delegate);
        return this;
    }

    public AdapterDelegateManage<T> addDelegate(int viewType, boolean allowReplacingDelegate, @NonNull AdapterDelegate<T> delegate) {
        if (!allowReplacingDelegate && delegates.get(viewType) != null) {
            throw new IllegalArgumentException(
                    "An ItemViewDelegate is already registered for the viewType = "
                            + viewType
                            + ". Already registered ItemViewDelegate is "
                            + delegates.get(viewType));
        }

        delegates.put(viewType, delegate);
        return this;
    }


    public int getItemViewType(int position, T adapterDataSource) {
        int delegateCount = delegates.size();
        for (int i = 0; i < delegateCount; i++) {
            AdapterDelegate<T> adapterDelegate = delegates.valueAt(i);
            if (adapterDelegate.isForViewType(position, adapterDataSource)) {
                return delegates.keyAt(i);
            }
        }
        throw new NullPointerException("No AdapterDelegate added that matches position=" + position + " in data source");
    }


    public int getAdapterDelegateCount() {
        return delegates.size();
    }


    public AdapterDelegate<T> getDelegateByViewType(int viewType) {
        return delegates.get(viewType);
    }

    public void convert(int position, T adapterDataSource, BaseViewHolder baseViewHolder) {
        int delegateCount = delegates.size();
        for (int i = 0; i < delegateCount; i++) {
            AdapterDelegate<T> adapterDelegate = delegates.valueAt(i);
            if (adapterDelegate.isForViewType(position, adapterDataSource)) {
                adapterDelegate.convert(position,baseViewHolder, adapterDataSource);
                return;
            }
        }
        throw new NullPointerException("No AdapterDelegate added that matches position=" + position + " in data source");
    }

提供一个各个模块统一的一接口AdapterDelegate<T>,以方便AdapterDelegateManager调用,接口如下:

/**
 * Adapter 模块代理接口
 *
 * @param <T> adapter 数据源 i.e List<BeanName>
 */
public interface AdapterDelegate<T> {


    @LayoutRes int getItemLayoutResId();


    /**
     * 判断
     *
     * @param position          itemview 在Adapter中的位置
     * @param adapterDataSource adapter 数据源
     * @return true item 是对应viewtype,false 不是
     */
    boolean isForViewType(int position, T adapterDataSource);

    /**
     * itemview中的子view 根据 数据,绘制界面
     *
     * @param position          itemview 在Adapter中的位置
     * @param baseViewHolder    与itemview绑定在一起的viewHolder
     * @param adapterDataSource adapter 数据源
     */
    void convert(int position, BaseViewHolder baseViewHolder, T adapterDataSource);
}

封装好之后,我们写两个类实现AdapterDelegate<T>接口:

  • CatAdapterDelegate
public class CatAdapterDelegate implements AdapterDelegate<List<BaseModel>> {

    @Override
    public int getItemLayoutResId() {
        return R.layout.cat_item;
    }

    @Override
    public boolean isForViewType(int position, List<BaseModel> adapterDataSource) {
        return adapterDataSource.get(position) instanceof Cat;
    }

    @Override
    public void convert(int position, BaseViewHolder baseViewHolder, List<BaseModel> adapterDataSource) {
        if (adapterDataSource.get(position) instanceof Cat) {
            Cat cat = (Cat) adapterDataSource.get(position);
            TextView textView = (TextView) baseViewHolder.getViewByViewId(R.id.id_tv_title);
            textView.setText(cat.getName());
        }
    }

}
  • DogAdapterDelegate
public class DogAdapterDelegate implements AdapterDelegate<List<BaseModel>> {

    @Override
    public int getItemLayoutResId() {
        return R.layout.dog_item;
    }

    @Override
    public boolean isForViewType(int position, List<BaseModel> adapterDataSource) {
        return adapterDataSource.get(position) instanceof Dog;
    }

    @Override
    public void convert(int position, BaseViewHolder baseViewHolder, List<BaseModel> adapterDataSource) {
        if (adapterDataSource.get(position) instanceof Cat) {
            Dog dog = (Dog) adapterDataSource.get(position);
            TextView textView = (TextView) baseViewHolder.getViewByViewId(R.id.id_tv_title);
            textView.setText(dog.getName());
        }
    }
}

CatAdapterDelegateDogAdapterDelegate 组装到我们的Adapter中:

public class MyMultiAdapter extends BaseAdapter {


    private Context context;
    private List<BaseModel> baseModelList;

    private AdapterDelegateManage<List<BaseModel>> adapterDelegateManage = new AdapterDelegateManage<>();

    public MyMultiAdapter(Context context, List<BaseModel> baseModelList) {
        this.context = context;
        this.baseModelList = baseModelList;

        adapterDelegateManage.addDelegate(new DogAdapterDelegate());
        adapterDelegateManage.addDelegate(new CatAdapterDelegate());

    }

    @Override
    public int getCount() {
        return baseModelList.size();
    }

    @Override
    public Object getItem(int position) {
        return baseModelList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return adapterDelegateManage.getItemViewType(position, baseModelList);
    }

    @Override
    public int getViewTypeCount() {
        return adapterDelegateManage.getAdapterDelegateCount();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        AdapterDelegate<List<BaseModel>> adapterDelegate = adapterDelegateManage.getDelegateByViewType(getItemViewType(position));
        BaseViewHolder baseViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(adapterDelegate.getItemLayoutResId(), parent, false);
            baseViewHolder = new BaseViewHolder(convertView);
            convertView.setTag(baseViewHolder);
        } else {
            baseViewHolder = (BaseViewHolder) convertView.getTag();
        }
        adapterDelegateManage.convert(position, baseModelList, baseViewHolder);
        return convertView;
    }
}

在外部调用:

public class MyListViewMultiBaseAdapterFragment extends BaseFragment {

    private List<BaseModel> mDatas = new ArrayList<>();

    @BindView(R.id.lv)
    ListView listView;


    public static MyListViewMultiBaseAdapterFragment newInstance() {
        MyListViewMultiBaseAdapterFragment fragment = new MyListViewMultiBaseAdapterFragment();
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initData();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_listivew_baseadapter, container, false);
        ButterKnife.bind(this, view);
        initView();
        return view;
    }

    private void initData() {
        mDatas.add(new Dog("dog1"));
        mDatas.add(new Dog("dog2"));
        mDatas.add(new Dog("dog3"));
        mDatas.add(new Cat("cat1"));
        mDatas.add(new Cat("cat2"));
        mDatas.add(new Cat("cat3"));

        Collections.shuffle(mDatas);
    }


    private void initView() {
        MyMultiAdapter adapter = new MyMultiAdapter(getContext(), mDatas);
        listView.setAdapter(adapter);

    }
}

最后我们在进一步封装我们的Adapter,将AdapterDelegateManage的调用封装到基础的MultiCommonAdpater

public class MultiCommonAdpater<T extends List<?>> extends BaseAdapter {

    private Context context;
    private T dataList;
    private AdapterDelegateManage<T> adapterDelegateManage = new AdapterDelegateManage<>();

    public MultiCommonAdpater(Context context, T dataList) {
        this.context = context;
        this.dataList = dataList;
    }

    @Override
    public int getCount() {
        return dataList.size();
    }

    @Override
    public Object getItem(int position) {
        return dataList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public int getItemViewType(int position) {
        return adapterDelegateManage.getItemViewType(position, dataList);
    }

    @Override
    public int getViewTypeCount() {
        return adapterDelegateManage.getAdapterDelegateCount();
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        AdapterDelegate<T> adapterDelegate = adapterDelegateManage.getDelegateByViewType(getItemViewType(position));
        BaseViewHolder baseViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(adapterDelegate.getItemLayoutResId(), parent, false);
            baseViewHolder = new BaseViewHolder(convertView);
            convertView.setTag(baseViewHolder);
        } else {
            baseViewHolder = (BaseViewHolder) convertView.getTag();
        }
        adapterDelegateManage.convert(position, dataList, baseViewHolder);
        return convertView;
    }

    protected MultiCommonAdpater addItemViewDelegate(AdapterDelegate<T> adapterDelegate) {
        adapterDelegateManage.addDelegate(adapterDelegate);
        return this;
    }
}

根据业务需要写一个Adapter时候,我们可以继承MultiCommonAdpater,如下:

public class MyNewMultiAdapter extends MultiCommonAdpater<List<BaseModel>> {

    public MyNewMultiAdapter(Context context, List<BaseModel> dataList) {
        super(context, dataList);
        addItemViewDelegate(new DogAdapterDelegate());
        addItemViewDelegate(new CatAdapterDelegate());
    }
}

是不是很简洁,一行代码就可以添加一种类型的Adapter,而且可以很方便的组装,我们还可以在AdapterDelegateManager中封装更多的方法,比如说,removeDeleagate()以实现删除某种item。

再来看看我们外层ListView使用:

public class MyListViewMultiBaseAdapterFragment extends BaseFragment {

    private List<BaseModel> mDatas = new ArrayList<>();

    @BindView(R.id.lv)
    ListView listView;


    public static MyListViewMultiBaseAdapterFragment newInstance() {
        MyListViewMultiBaseAdapterFragment fragment = new MyListViewMultiBaseAdapterFragment();
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initData();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_listivew_baseadapter, container, false);
        ButterKnife.bind(this, view);
        initView();
        return view;
    }

    private void initData() {
        mDatas.add(new Dog("dog1"));
        mDatas.add(new Dog("dog2"));
        mDatas.add(new Dog("dog3"));
        mDatas.add(new Cat("cat1"));
        mDatas.add(new Cat("cat2"));
        mDatas.add(new Cat("cat3"));

        Collections.shuffle(mDatas);
    }


    private void initView() {
//        listView.setAdapter(new MultiCommonAdpater<>(getContext(), mDatas));

        listView.setAdapter(new MyNewMultiAdapter(getContext(), mDatas));
    }
}


好了,至此关于Adapter两种封装模式总结完成了,源码可以看下面参考资料中的两个开源库。

参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容