蜗牛君漫聊动态布局框架(三):适配器与创建者

2023-11-15

大家好,欢迎来到蜗牛君漫聊动态布局框架专题。上篇文章中我们介绍完了框架的核心功能实现,本篇继续介绍剩下的所有功能。

不同类型ViewHolder的动态创建已经完成,接下来我们要实现数据与布局的中间件—适配器(Adapter)。

代码实现:中间件—适配器

Adapter类

需要做到一下几点:

  • 继承官方的Adapter类,并传递BaseViewHolder类作为泛型参数;
  • 渲染数据的管理
  • 实例化ViewHolderFactory
  • Adapter四大方法的实现:onCreateViewHolder、onBindVievHolder、getItemCount、getItemViewType
/**
 * 职责:
 * 1、数据管理
 * 2、实例化ViewHolderFactory
 * 3、完成四大方法的具体实现
 */
public class RecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private ViewHolderFactory mFactory;
    private List<Object> dataList = new ArrayList<>();

    /**
     * 使用指定工厂类
     * 
     * @param context
     */
    public RecyclerAdapter(Context context) {
        this(new ViewHolderFactory(context));
    }

    /**
     * 手动指定工厂类
     *
     * @param factory
     */
    public RecyclerAdapter(ViewHolderFactory factory) {
        mFactory = factory;
    }

    /**
     * 创建Item所需要的ViewHolder
     *
     * @param parent
     * @param viewType
     * @return
     */
    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return mFactory.create(viewType, parent);
    }

    /**
     * 将数据与视图进行绑定
     *
     * @param holder
     * @param position
     */
    @SuppressWarnings("unchecked")
    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        holder.bindTo(position, dataList.get(position), this);
    }

    /**
     * Item总数
     *
     * @return
     */
    @Override
    public int getItemCount() {
        return dataList.size();
    }

    /**
     * 返回当前Item的布局类型
     *
     * @param position
     * @return 当前数据类型在索引集合中的下标
     */
    @Override
    public int getItemViewType(int position) {
        return mFactory.itemViewType(dataList.get(position));
    }

    /**
     * 添加数据
     *
     * @param list
     */
    public void addAll(List<?> list) {
        dataList.clear();
        if (list != null && !list.isEmpty()) {
            dataList.addAll(list);
        }

        notifyDataSetChanged();
    }
}

注意:这里有很多的细节没有讲,例如关于参数类型设置:Object、泛型、占位符的选择;这些基础知识需要大家自行补充了,其中的用意也需要大家自己品味一下,这些细节很重要。

代码实现:建造者模式的使用

1、RecyclerConfig
  • 创建者模式提供链式调用与组合配置;
  • 创建RecyclerView的配置,除去配置RecyclerView的四大元素之外,还要配置绑定数据类型与ViewHolder的关系、自定义ViewHolderFactory、是否支持刷新等等。
public class RecylerConfig {
    private RecyclerView.LayoutManager mLayoutMananger;
    private RecyclerView.ItemDecoration mItemDecoration;
    private RecyclerView.ItemAnimator mItemAnimator;
    private ViewHolderFactory mViewHolderFactory;
    private Map<Class, Class<? extends BaseViewHolder>> mBoundViewHolder;
    private boolean mEnable = true;

    public RecyclerView.LayoutManager getLayoutMananger() {
        return mLayoutMananger;
    }

    public RecyclerView.ItemDecoration getItemDecoration() {
        return mItemDecoration;
    }

    public RecyclerView.ItemAnimator getItemAnimator() {
        return mItemAnimator;
    }

    public Map<Class, Class<? extends BaseViewHolder>> getBoundViewHolder() {
        return mBoundViewHolder;
    }

    public boolean enableRefresh() {
        return mEnable;
    }

    public static class Builder {
        private RecyclerView.LayoutManager mLayoutMananger;
        private RecyclerView.ItemDecoration mItemDecoration;
        private RecyclerView.ItemAnimator mItemAnimator;
        private ViewHolderFactory mViewHolderFactory;
        private Map<Class, Class<? extends BaseViewHolder>> mBoundViewHolder;
        private boolean mEnable = true;

        public Builder layoutManager(RecyclerView.LayoutManager layoutMananger) {
            this.mLayoutMananger = layoutMananger;
            return this;
        }

        public Builder itemDecoration(RecyclerView.ItemDecoration itemDecoration) {
            this.mItemDecoration = itemDecoration;
            return this;
        }

        public Builder itemAnimator(RecyclerView.ItemAnimator itemAnimator) {
            this.mItemAnimator = itemAnimator;
            return this;
        }

        public Builder viewHolderFactory(ViewHolderFactory viewHolderFactory) {
            this.mViewHolderFactory = viewHolderFactory;
            return this;
        }

        public Builder bind(Class valueClassType, Class<? extends BaseViewHolder> viewHolder) {
            this.mBoundViewHolder.put(valueClassType, viewHolder);
            return this;
        }

        public Builder enableRefresh(boolean enable) {
            this.mEnable = enable;
            return this;
        }

        public RecylerConfig build() {
            RecylerConfig config = new RecylerConfig();
            config.mLayoutMananger = this.mLayoutMananger;
            config.mItemDecoration = this.mItemDecoration;
            config.mItemAnimator = this.mItemAnimator;
            config.mBoundViewHolder = this.mBoundViewHolder;
            config.mViewHolderFactory = this.mViewHolderFactory;
            config.mEnable = this.mEnable;
            return config;
        }
    }
}
2、调度 RecyclerViewLayoutActivity.java
// 关联布局文件
@BindView(R.id.recycler_view_layout)
RecyclerView mRecyclerView;

// 主布局
setContentView(R.layout.recycler_view_layout_activity);

// 初始化Adapter
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(this);
// 初始化LayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
// 初始化下划线
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);

// 通过RecyclerConfig组装RecyclerView配置
RecyclerConfig config = new RecyclerConfig.Builder()
        .layoutManager(linearLayoutManager)
        .itemDecoration(itemDecoration)
        .bind(CommonModel.class, CommonViewHolder.class)
        .enableRefresh(false)
        .build();
buildConfig(config);

// 进行最终的设置
mRecyclerView.setAdapter(mRecyclerAdapter);
mRecyclerView.setLayoutManager(config.getLayoutMananger());
mRecyclerView.addItemDecoration(config.getItemDecoration());

recycler_view_layout_activity.xml

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintStart_toStartOf="parent"
    tools:ignore="MissingConstraints"
    tools:layout_editor_absoluteY="0dp" />

RecyclerView动态布局框架的基础结构讲解完毕,上述框架能够实现基本的布局功能,为了大家读起来更直接,有些封装拆开了平铺展示给大家。最后,给大家总结一下我分析出来的要点。

第一点,思路的根源是RecyclerView能够通过getItemViewType方法动态确定当前Item需要使用的ViewHolder;

第二点:使用Java的反射机制动态创建ViewHolder;

第三点:工厂模式的使用;

第四点:数据类型和ViewHolder一一对应关系的存储方式;

只要大家掌握了上述四点,就能够在RecyclerView的基础使用上封装出适合自己业务的动态布局框架。本篇文章的内容到这里就结束了,通过三篇文章我们将动态布局框架最核心最重要的东西都讲解完了。不过,我们只是实现了通用的功能,还有很多辅助功能还没有实现,因此我们这个专题并不会就此结束,后续文章中我们会介绍监听事件的添加、RecyclerViewAdapter中数据的管理功能、删除某一项、增加某一项功能等等。那就让我们相约下一期吧,再见~
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

蜗牛君漫聊动态布局框架(三):适配器与创建者 的相关文章

随机推荐

  • 有1、2、3、4四个数字,可以组成多少个互不相同且无重复的三位数?都是多少?

    这个题呢 顾名思义 就是说一个三位数的每一位都是1 2 3 4 个位十位百位上的数字不能重复 编程原理很简单 分别定义三个变量代表个位十位百位 然后使用for循环嵌套每一层循环代表一位数 如果个位十位百位都不相同 则输出 程序如下 incl
  • 微信订阅消息模板推送报错47003 data.time.value i,及解决方案

    今天又是枯燥的一天 依然敲着代码 客户有个微信消息推送的需求 找了下官方文档 微信消息推送文档 大致看了一下 需要模板ID和微信后台的小卡片参数名 随即便敲起了代码 首先定义模板类 代码如下 public class Template pr
  • 微信小程序实现一些炫酷的loading动画

    1 实现效果 2 实现原理 伪元素 css3动画 transform 3 实现代码 从上到下 从左到右依次的代码如下
  • 三款记事本替代工具 哪个最好用?

    三款记事本替代工具 哪个最好用 http www sina com cn 2008年08月27日 08 35 IT168 com Windows操作系统中自带了不少的实用小程序 但是它们大都功能简陋 有时无法满足我们的使用 此外还有一些Wi
  • MatplotLib 第二部分

    1 import numpy as np 2 import pandas as pd 3 import matplotlib pyplot as plt 4 5 导入数据 6 df pd read excel d test xlsx 7 p
  • 在VS中使用命令行参数

    在VS工具中 若要运行带有命令行参数的程序 有两种方法 方法一 在命令提示符中输入要运行的exe的文件名和要输入的参数 各参数之间用空格隔开 如exe文件为test exe 则输入 test 参数1 参数2 参数n 注意 exe文件应放在C
  • 我的软件渲染器终于初步完成了~

    记录一个大好事 在 2021年第一个月的上旬 我的软件着色器终于初具雏形了 中间参考了 很多 资料 最初是 知乎上的系列教程 https zhuanlan zhihu com p 141210744 这个教程是基于 OpenGL 右手坐标系
  • 什么是准双向口,双向口?

    C51的说明书上说 Because Ports 1 2 and 3 have fixed internal pullups they are sometimes called quasi bidirectional ports When c
  • golang 杂技

    Swap 记录一个骚操作 交换数组的两个元素 package main import fmt func main m int 1 2 Swap m 0 1 fmt Println m 2 1 func Swap i int a b int
  • C语言方波转换正弦波,方波转换成正弦波电路

    方波转换成正弦波电路 即利用RDD104可选的4各十进制CMOS除法器和一个MSFS5 开关电容滤波器来构建一个双芯片 失真率为0 2 的正弦波源 RDD104有两个引脚 可以从四个除法器divide by 10 divide by 100
  • 离线数仓经验之谈三-数仓流程规范

    数仓流程规范 目录 1 目的 2 适用范围 3 总体流程 3 1 ETL开发流程 3 1 1 需求分析 3 1 2 数据来源与数据探查 3 1 3 数据模型设计 3 1 4 ETL开发 3 1 5 测试 3 1 6 ETL上线 3 1 7
  • 想入手显示器,恳请粉丝带我推荐,必有重谢!

    坏了一个显示器 本来家里好好的两个显示器 其中1个有点雪花亮线 当时特地买的EIZO 考虑已无维修价值 打算换一个显示器 但是某宝搜了一圈 已经被各种参数和品牌搞晕掉 2K 4K 准4K IPS 60hz 144HZ 高刷 曲面屏 带鱼屏
  • 队列数据类型及Python实现

    1 队列的实现 队列是一种有次序的数据集合 其特征是 新数据项的添加总发生在一端 通常称为尾端 rear 而现存数据类型的移除总发生在另一端 通常称为首段 front 当数据项加入队列 首先出现在队尾 随着队首数据项的移除 它逐渐接近队首
  • NEZHA知识点

    1 华为NEZHA 主要是将bert之后预训练模型的长处拼接在一起 1 相对位置编码 Bert的位置编码是直接初始化一个embedding 然后通过预训练去学的 是固定位置编码 NEZHA使用函数式相对位置编码 在qk时 加在k上 表示q和
  • Trie树(字典树,单词查找树)

    例题引入 题目传送门于是他错误的点名开始了 题目大意 给出n个单词 有m个询问 每次给出一个单词 如果这个单词出现过且是第一次出现 输出 OK 如果这个单词没有出现过 输出 WRONG 如果这个单词出现过但不是第一次出现 输出 REPEAT
  • how to

    打开一个virtualfile VirtualFile file Project project OpenFileDescriptior descriptor new OpenFileDescriptior file navigate Fi
  • PROFIBUS DP从站开发 VPC3源程序分析---vpc3_get_dinbufptr (void)函数

    UBYTE PTR ATTR vpc3 get dinbufptr void 以下程序注释由成都地质学院霸王猫添加 引用时请尊重作者劳动成果 标明引用者来自成都地质学院霸王猫 UBYTE PTR ATTR vpc3 get dinbufpt
  • hadoop habse集群增加磁盘空间

    最近项目上采集的数据量超出预期 hbase集群中的datanode节点磁盘使用过快 基本都超过50 按现有的使用频率来看 预计只能继续支撑3个月左右 考虑着要加新的硬盘 但是却被这么一个小问题折腾了好一会才解决 特地在此记录一下 cento
  • Webstorm的介绍

    WebStorm 是什么 WebStorm 是jetbrains公司旗下一款JavaScript 开发工具 被广大中国JS开发者誉为 Web前端开发神器 最强大的HTML5编辑器 最智能的JavaScript IDE 等 与IntelliJ
  • 蜗牛君漫聊动态布局框架(三):适配器与创建者

    大家好 欢迎来到蜗牛君漫聊动态布局框架专题 上篇文章中我们介绍完了框架的核心功能实现 本篇继续介绍剩下的所有功能 不同类型ViewHolder的动态创建已经完成 接下来我们要实现数据与布局的中间件 适配器 Adapter 代码实现 中间件