BaseRecyclerViewAdapterHelper 开源项目之 BaseMultiItemQuickAdapter 实现多类型源码学习

本贴最后更新于 2520 天前,其中的信息可能已经时移世异

version:2.8.5

今天我们来看下 BaseRecyclerViewAdapterHelper 是如何实现多布局的。

首先我们要实现多类型布局,我们的 adapter 不再是继承自 BaseQuickAdapter 类,而是继承自其的子类 BaseMultiItemQuickAdapter。而且数据源类型需要继承自 MultiItemEntity,MultiItemEntity 是一个接口,代码很少:

package com.chad.library.adapter.base.entity;

/**
 * https://github.com/CymChad/BaseRecyclerViewAdapterHelper
 */
public interface MultiItemEntity {

    int getItemType();

}

其主要用意是我们的数据源继承 MultiItemEntity,这样子,我们可以在数据源中动态的返回一个 int 类型的数值(代表某一类型的 item),大家可以想一下,我们在渲染 viewholder 的时候,如果想实现多类型的 viewholder,而 viewholder 的类型展示又跟所需绑定的数据息息相关,那么如果我们在数据源中提供一种确定 viewholder 类型的能力,理论上是不是就可以达到我们要的效果了?我们带着这样的一个假设继续往下看。而这个 BaseMultiItemQuickAdapter 是何许人也,是如何实现多类型布局的呢?我们来看下源码:

package com.chad.library.adapter.base;

import android.support.annotation.LayoutRes;
import android.util.SparseArray;
import android.view.ViewGroup;

import com.chad.library.adapter.base.entity.MultiItemEntity;

import java.util.List;

/**
 * https://github.com/CymChad/BaseRecyclerViewAdapterHelper
 */
public abstract class BaseMultiItemQuickAdapter extends BaseQuickAdapter<T, K> {

    /**
     * layouts indexed with their types
     */
    private SparseArray layouts;

    private static final int DEFAULT_VIEW_TYPE = -0xff;

    /**
     * Same as QuickAdapter#QuickAdapter(Context,int) but with
     * some initialization data.
     *
     * @param data    A new list is created out of this one to avoid mutable list
     */
    public BaseMultiItemQuickAdapter( List data) {
        super( data);
    }

    @Override
    protected int getDefItemViewType(int position) {
        Object item = mData.get(position);
        if (item instanceof MultiItemEntity) {
            return ((MultiItemEntity)item).getItemType();
        }
        return DEFAULT_VIEW_TYPE;
    }

    protected void setDefaultViewTypeLayout(@LayoutRes int layoutResId) {
        addItemType(DEFAULT_VIEW_TYPE, layoutResId);
    }

    @Override
    protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
        return createBaseViewHolder(parent, getLayoutId(viewType));
    }

    private int getLayoutId(int viewType) {
        return layouts.get(viewType);
    }

    protected void addItemType(int type, @LayoutRes int layoutResId) {
        if (layouts == null) {
            layouts = new SparseArray<>();
        }
        layouts.put(type, layoutResId);
    }

}

源码不多:

字段解析:

1、存储我们的布局资源的 ids

    private SparseArray layouts;

2、缺省的布局类型值,当使用多布局时,在渲染 viewholder 的时候类型址不是我们配置的类型值中,就会使用这个。

    private static final int DEFAULT_VIEW_TYPE = -0xff;

接下来,我们以一个 BaseMultiItemQuickAdapter 的创建过程来分析代码:

之前我们分析了 BaseQuickAdapter 的代码,其执行过程是一样的,我们实现多布局功能的切入口无非是

1、在执行 getItemViewType 时的能够根据我们的数据源返回对应的布局类型值。

2、在 onCreateDefViewHolder 能够正确拿到类型值进行 viewholder 的渲染。

3、我们在 onBindViewHolder 中根据传递给我们的数据源中接口定义的 getItemViewType 方法返回的类型值来确定当前的 viewholder 是什么类型的,需要绑定什么数据。

(注:之前分析了 adapter 的加载数据时的生命周期方法:getItemViewType->onCreateDefViewHolder->onBindViewHolder,如果不大清楚可以看下前面的文章)

所以,我们在 BaseMultiItemQuickAdapter 里面重写了 getDefItemViewType 方法,为什么时重写 getDefItemViewType 方法而不是 getItemViewType 方法呢?这可不是我糊弄你,因为我们在 BaseQuickAdapter 里面重写了 getItemViewType 方法,而在 getItemViewType 方法里调用了 getDefItemViewType 方法来回去类型值,该方法也在之前的分析 BaseQuickAdapter 源码的文章中分析了的。
重写之后做了什么呢?看代码:

@Override
    protected int getDefItemViewType(int position) {
        Object item = mData.get(position);
        if (item instanceof MultiItemEntity) {
            return ((MultiItemEntity)item).getItemType();
        }
        return DEFAULT_VIEW_TYPE;
    }

很简单,因为我们的数据源实现了 MultiItemEntity 接口。直接判断该 position 的数据是不是实现了 MultiItemEntity 接口,是调用接口的 getItemType 方法返回类型值,不是返回默认类型值。
第一步返回类型值的代码改造完成了,接下来第二部就是根据类型值渲染 viewholder。BaseMultiItemQuickAdapter 直接重写了 onCreateDefViewHolder 方法来实现该扩展:

    @Override
    protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
        return createBaseViewHolder(parent, getLayoutId(viewType));
    }

代码很简单,从我们存储布局缓存的字段中根据 viewType 返回对象的布局资源的 ids。
所以 BaseMultiItemQuickAdapter 还给我们包装了一个 addItemType 方法:

protected void addItemType(int type, @LayoutRes int layoutResId) {
        if (layouts == null) {
            layouts = new SparseArray<>();
        }
        layouts.put(type, layoutResId);
    }

该方法很简单,就是将不同的布局资源的 ids 和对应的类型值存储起来。
所以我们的创建多布局的时候,需要的构造函数中调用 addItemType 来添加不同的布局资源
最后一步,绑定数据;一般绑定数据实在 onBindViewHolder 中实现的,而我们的 BaseRecyclerViewAdapterHelper 对其进行了包装,提供了一个 convert 方法,所以我们只需要在 convert 方法中根据数据源数据节点的类型值判断绑定的是那个布局的数据即可。
总结:理解了 adapter 加载数据的生命周期方法的执行顺序很重要(getItemViewType->onCreateDefViewHolder->onBindViewHolder)。

只要控制 viewType 的返回、viewholder 的渲染。viewholder 数据的绑定即可。

  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    333 引用 • 323 回帖 • 65 关注
  • int
    12 引用 • 18 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    你好。请问可以发个 多类型 demo看看么? 谢谢了

  • someone

    你好,这个在BaseRecyclerViewAdapterHelper的官网有demo apk哦

  • someone

    你好,这个在BaseRecyclerViewAdapterHelper的官网有demo apk哦

  • someone

    你好,这个在BaseRecyclerViewAdapterHelper的官网有demo apk哦

推荐标签 标签

  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    532 引用 • 3528 回帖
  • 分享

    有什么新发现就分享给大家吧!

    242 引用 • 1747 回帖
  • CodeMirror
    1 引用 • 2 回帖 • 116 关注
  • OnlyOffice
    4 引用 • 24 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 636 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 439 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 390 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    207 引用 • 2031 回帖
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    313 引用 • 1666 回帖 • 1 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    85 引用 • 1201 回帖 • 449 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 1 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 3 关注
  • 博客

    记录并分享人生的经历。

    270 引用 • 2386 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 455 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    228 引用 • 1450 回帖 • 1 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 34 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    90 引用 • 383 回帖 • 1 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 286 关注