孟老板 ListAdapter封装, 告别Adapter代码 (上)
- BaseAdapter封装(一) 简单封装
- BaseAdapter封装(二) Header,footer
- BaseAdapter封装(三) 空数据占位图
- BaseAdapter封装(四) PageHelper
- BaseAdapter封装(五) ListAdapter
- ListAdapter封装, 告别Adapter代码 (上)
- ListAdapter封装, 告别Adapter代码 (中)
- ListAdapter封装, 告别Adapter代码 (下)
- BaseAdapter封装(八) Paging 分页
ListAdapter封装 (上) - SimpleAdapter
前言:
上一篇文章已经讲解 ListAdapter 的基本使用; 这次 我们不再关心 实体类型、Item事件回调, 编写统一 DiffCallback, 布局ID传入.
使用:
1. 首先新建 BaseItem: 列表实体都会实现此接口. 它是 BaseAdapter 的默认实体类型
interface BaseItem {
/**
* 条目更新标记, 用于 DiffUtil areContentsTheSame
*/
var hasChanged: Boolean
/**
* Adapter 中的 ItemType.
* 单类型布局可以不用关心 该返回值
* 多类型布局中; 需直接返回布局Id; 例如: R.layout.item_test
*/
fun getMItemType(): Int = 0
}
2. 再创建实体类, 实现 BaseItem 接口; 除了 hasChanged, 只有一个 title 参数;
class TestEntity(
var title: String? = null,
override var hasChanged: Boolean = false
) : BaseItem
3.编写通用的 DiffCallback; 实体类型就用 BaseItem
areItemsTheSame(): 我们选用比较内存地址的方式;
areContentsTheSame(): 我们选择状态标记方式;
class DiffCallback: DiffUtil.ItemCallback<BaseItem>() {
/**
* 比较两个条目对象 是否为同一个Item
*/
override fun areItemsTheSame(oldItem: BaseItem, newItem: BaseItem): Boolean {
return oldItem === newItem
}
/**
* 再确定为同一条目的情况下; 再去比较 item 的内容是否发生变化;
* 我们使用 状态标识方式判断;
* @return true: 代表无变化; false: 有变化;
*/
override fun areContentsTheSame(oldItem: BaseItem, newItem: BaseItem): Boolean {
return !oldItem.hasChanged
}
}
4.接下来是 ViewHolder: 用于 item 绑定数据,及缓存控件. 我们加入事件处理 handler; 以及重置状态标记;
open class NewViewHolder(val binding: ViewDataBinding, private val handler: BaseHandler?) : RecyclerView.ViewHolder(binding.root){
open fun bind(item: BaseItem?) {
//重置 状态标记
item?.hasChanged = false
binding.setVariable(BR.item, item)
binding.setVariable(BR.handler, handler)
binding.executePendingBindings()
}
}
5. Handler : MVVM 模式中 Item事件响应处理类;
基类: BaseHandler 它几乎只出现在 Adapter相关基类中,省的我们再写泛型; 要使用还得用它的子类
子类: Handler 提供具体实体泛型. 供布局文件使用
/**
* item 事件响应基类, 这类什么都不用写
*/
open class BaseHandler /**
* item 事件响应基类, 需提供具体的实体类泛型;
*/
abstract class Handler<T: BaseItem> : BaseHandler() {
abstract fun onClick(view: View, info: T)
}
6.下面是重头戏了: BaseAdapter
重头戏?但它却如此简单 [捂脸] (自带转义); 只需要传入 BaseHandler 对象; 并重写 onBindViewHolder 即可;
我还重写了 submitList(); 因为ListAdapter 提交数据时,会判断前后数据集合是否为同一内存地址; 我们让它必定以新数据集对象传入; (虽然个人感觉这样不对, 但博主还就踩上这坑了 [机智])
abstract class BaseAdapter(
protected val handler: BaseHandler? = null) :
ListAdapter<BaseItem, NewViewHolder>(DiffCallback()) { override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
holder.bind(getItem(position))
} /**
* 重写 提交数据方法, 让它必定以新数据集合对象传入
*/
override fun submitList(list: MutableList<out BaseItem>?) {
val newData = mutableListOf<BaseItem>()
if (list != null) {
newData.addAll(list)
}
super.submitList(newData)
}
}
7. 重头戏中的重头来了 SimpleAdapter:
好吧, 它更简单. 继承 BaseAdapter 并传入 layoutId, 再重写 onCreateViewHolder 即可;
open class SimpleAdapter(
/**
* 布局id;
*/
private val layout: Int,
handler: BaseHandler? = null
) :
BaseAdapter(handler) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
return NewViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context), layout, parent, false
), handler
)
}
}
8. 好了封装完事. 接下来我们要开始用了! 使用也非常简单
//只需要传入 布局id 及 事件响应 Handler
mAdapter = SimpleAdapter(R.layout.item_test_mvvm, object : Handler<TestEntity>(){
override fun onClick(view: View, info: TestEntity) {
Toast.makeText(mActivity, "点了条目", Toast.LENGTH_SHORT).show()
}
})
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = mAdapter
}
val data = mutableListOf(TestEntity("第一条"), TestEntity("第一条"), TestEntity("第一条"), TestEntity("第一条"), TestEntity("第一条"))
mAdapter.submitList(data)
9. 好吧,再贴出我的 布局文件:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="com.example.kotlinmvpframe.network.entity.TestEntity" />
<variable
name="handler"
type="com.example.kotlinmvpframe.test.testtwo.Handler" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:onClick="@{(view) -> handler.onClick(view, item)}"
android:padding="20dp">
<TextView
android:id="@+id/btn2"
style="@style/tv_base_16_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.title}" />
</LinearLayout>
</layout>
好的! over
下一篇再讲 多条目类型, 嵌套RecycleView, 封装头尾 等等! 敬请期待
孟老板 ListAdapter封装, 告别Adapter代码 (上)的更多相关文章
- 孟老板 ListAdapter封装, 告别Adapter代码 (三)
BaseAdapter系列 ListAdapter封装, 告别Adapter代码 (一) ListAdapter封装, 告别Adapter代码 (二) ListAdapter封装, 告别Adapter ...
- 孟老板 ListAdapter封装, 告别Adapter代码 (四)
BaseAdapter系列 ListAdapter封装, 告别Adapter代码 (一) ListAdapter封装, 告别Adapter代码 (二) ListAdapter封装, 告别Adapter ...
- 孟老板 BaseAdapter封装(五) ListAdapter
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- 孟老板 BaseAdapter封装 (三) 空数据占位图
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- 孟老板 BaseAdapter封装(四) PageHelper
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- 孟老板 BaseAdapter封装 (一) 简单封装
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- 孟老板 BaseAdapter封装 (二) Healer,footer
BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...
- 对百度WebUploader的二次封装,精简前端代码之图片预览上传(两句代码搞定上传)
前言 本篇文章上一篇: 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传) 此篇是在上面的基础上扩展出来专门上传图片的控件封装. 首先我们看看效果: 正文 使用方式同 ...
- 孟老板 Paging3 (二) 结合Room
BaseAdapter系列 ListAdapter系列 Paging3 (一) 入门 Paging3 (二) 结合 Room Paging3 (二) 结合Room Paging 数据源不开放, 无法 ...
随机推荐
- 安装全局消息钩子实现dll窗体程序注入
说明{ 通过设置全局消息钩子来实现dll注入,然后窗体有相关消息请求的时候就会自动加载注入dll, 然后在入口处做处理就可以了.注入方式简单很多,比代码注入和lsp等注入都简单,就不解释了. ...
- 前端小白的学习之路html与css的较量【一】
html和css的较量 web结构的组成 html标签规则 快速生成一个html html的基本结构 标签的关系 标签 标题标签 段落 图片 超链接 a 属性 a标签里面的值 字符实体 新增的标签 1 ...
- ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule
解释:执行docker-compose up -d时出现ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule 原因:防火墙 ...
- dubbo服务暴露原理
1.发布流程 暴露本地服务 暴露远程服务 启动netty 连接zookeeper 到zookeeper注册 监听zookeeper 2.官方文档 3.看输出日志,就会发现在暴露本地服务之前,有一句很重 ...
- 解决客户端Redis中文乱码问题
启动客户端的时候添加 --raw 选项即可 wangyulong@code-local:~$ redis-cli 127.0.0.1:6379> set key1 '上海' OK 127.0.0 ...
- 浅析DDD——领域驱动设计的理解
浅析DDD--领域驱动设计的理解 我觉得领域驱动设计概念的提出,是为了更清晰的区分边界.这里的边界包括业务边界和功能的边界,每个边界都包含具体的领域对象,当业务和功能的领域对象一一对应上之后,业务的变 ...
- Java_接口回调与匿名内部类
匿名内部类 警告:匿名内部类本质上是一个对象 如果有一个接口或者抽象类,必须要用class定义一个实现类写重写抽象方法,才能创建对象并使用. 匿名内部类就是省略了用class定义子类的过程,直接使用父 ...
- OOP第四章博客
OOP第四章博客作业 (1)本单元作业架构设计 1)针对于第一次作业,我是将所给类进行了自己的封装,在MyUmlInteraction类里面进行关系的建立,这里把所给的UmlClass建立好,同时有i ...
- Pytorch实现对卷积的可插拔reparameterization
需要实现对卷积层的重参数化reparameterization 但是代码里卷积前weight并没有hook,很难在原本的卷积类上用pure oo的方式实现 目前的解决方案是继承原本的卷积,挂载一个we ...
- Pytorch系列:(六)自然语言处理NLP
这篇文章主要介绍Pytorch中常用的几个循环神经网络模型,包括RNN,LSTM,GRU,以及其他相关知识点. nn.Embedding 在使用各种NLP模型之前,需要将单词进行向量化,其中,pyto ...