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代码 (上)的更多相关文章

  1. 对百度WebUploader的二次封装,精简前端代码之图片预览上传(两句代码搞定上传)

    前言 本篇文章上一篇: 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传) 此篇是在上面的基础上扩展出来专门上传图片的控件封装. 首先我们看看效果: 正文 使用方式同 ...

  2. AngularJS之使用服务封装可复用代码

    创建服务组件 在AngularJS中创建一个服务组件很简单,只需要定义一个具有$get方法的构造函数, 然后使用模块的provider方法进行登记: //定义构造函数 var myServicePro ...

  3. 玩转UITableView系列(一)--- 解耦封装、简化代码、适者生存!

    UITableView这个iOS开发中永远绕不开的UIView,那么就不可避免的要在多个页面多种场景下反复摩擦UITableView,就算是刚跳进火坑不久的iOS Developer也知道实现UITa ...

  4. volley+okhttp封装,一行代码就可访问网络

    volley+okhttp封装,一行代码就可访问网络 前言: 我写这个可能不会完全的教会你去怎么封装一个网络框架,我的目的在于让你不需要你自己封装就可以访问网络,或者说互相学习也可以,我只是想让你大概 ...

  5. Visual Studio 创建封装自己的代码段(C#)

    https://www.cnblogs.com/awaTangjay/p/6644952.html 1.打开vs2012--工具--代码段管理器 2.进入代码管理器之后,语言选择Visual C#,然 ...

  6. 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码

    VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...

  7. 将你的代码上传 Bintray 仓库

    在 Android Studio 中,我们通常可以利用 gradle 来导入别人写的第三方库,通常可以简单得使用一句话就能搞定整个导包过程, 比如: compile 'net.cpacm.moneyt ...

  8. git使用之如何将github库下载到本地与如何将代码上传github

    git使用之如何将github库下载到本地与如何将代码上传github ---------------------------------------------------------------- ...

  9. 一步一步实现android studio代码上传到github。

    本文只注重代码上传能成功就好,不解释什么是git什么事github,git有什么优势. 1,先创建一个android应用, 第二步:创建github账户 和 安装git.网上的文章多如牛毛.唯一要说的 ...

  10. nginx+vsftp图片下载java代码上传

    系统环境:阿里云centos7.3 安装nginx 查看nginx进程 ps aux|grep nginx 在/usr/local/nginx/sbin/目录下 nginx启动 ./nginx 快速停 ...

随机推荐

  1. phpize 扩展GD库 安装 ! 环境--centos 7 +nginx 1.7.11+php 5.6.7

    使用phpize编译GD库安装,先安装前置库libjpeg libpng zlib  freetype等 都是下面php编译的几个选项 先看php编译的选项: --with-gd=DIR       ...

  2. Spark官方文档——本地编写并运行scala程序

    快速开始 本文将介绍如何用scala.java.python编写一个spark单击模式的程序. 首先你只需要在一台机器上成功建造Spark:做法: 进入Spark的根目录,输入命令:$ sbt/sbt ...

  3. 解决方案:Error:Execution failed for task &#39;:app:compileDebugAidl&#39;. &gt; aidl is missing

    也许有朋友最初在用Android Studio创建新工程的时候会碰到这个错误,其实这个问题是由于版本不兼容导致的,解决方法很简单,只需要把编译工具的版本改一下就可以了: 1.选左侧的工程根目录app, ...

  4. C语言sizeofkeyword

    说明: ******C语言sizeof是keyword.是一个操作符.它不是一个函数.用于计算可变.或内存数据字节数占用类型. ******sizeof有三种不同的方式: ***sizeof(变量名) ...

  5. CSS3秘笈:第八章

    给网页添加图片 1. 常用来处理图片的CSS属性: (1)     border(边框):给图片添加边框. (2)     padding(填充):边框和图片之间填充空间. (3)     float ...

  6. windos下安装pgAdmin

    1.进入pgAdmin官方网址 https://www.pgadmin.org/download/ 2.下载安装包 版本下载地址:https://www.pgadmin.org/download/pg ...

  7. 微信小程序-转发

    仅供参考 1,js: onShareAppMessage(res) { return { title: '我在使用俺搜·找客户,10万+材料人都在用,就差你了', path: '/pages/inde ...

  8. spoj 1825 Free tour II

    http://www.spoj.com/problems/FTOUR2/ After the success of 2nd anniversary (take a look at problem FT ...

  9. C#读取Excel技术概览 (2)

    5.自定义SDK,使用xmlReader文件流式处理 第四章节中,总是感觉用别人的工具要受制于人.既然我 们知道了Excel的存储方式,问题便转换成从xml中取出数据,然后放入内存得到我们想要的东西, ...

  10. Crystal Report保留小数位

    If IsNull({DECL_INV_ITEM_I.DECLEAR_NO}) Or Trim({DECL_INV_ITEM_I.DECLEAR_NO}) = "" Then &q ...