android开源系统brvah,Android Jetpack之通用Adapter(Databinding+BRVAH)

之前发过一个databinding版的通用adapter,能实现一般需求,不过功能比较简陋,实际开发中大家更倾向于使用BRVAH等功能丰富的第三方框架。现在给出一个基于BRVAH的databinding版通用Adapter。

BaseAdapter

abstract class BaseAdapter

(private val brId: Int, layoutId: Int, dataList: MutableList?)

: BaseQuickAdapter(layoutId, dataList) {

...

}

构造函数比较长,两个泛型,T代表item的model类型即dataList的bean类型,TBinding代表itemLayout对应生成的XXXBinding类,比如itemLayout是fruit_item.xml,对应的就是FruitItemBinding。三个个参数dataList和layoutId应该不用解释,brId则对应itemLayout里相应variable的变量名,比如variable的name是fruit,brId就是BR.fruit。

数据绑定

override fun onItemViewHolderCreated(viewHolder: BaseViewHolder, viewType: Int) {

DataBindingUtil.bind(viewHolder.itemView)

}

final override fun convert(helper: BaseViewHolder, item: T) = convert(helper, item, helper.layoutPosition)

//final override fun convert(helper: BaseViewHolder, item: T, payloads: List) = convert(helper, item, helper.layoutPosition, payloads)

protected open fun convert(holder: BaseViewHolder, item: T, position: Int) {

holder.getBinding()?.apply {

setVariable(brId, item)

executePendingBindings()

}

}

//protected open fun convert(holder: BaseViewHolder, item: T, position: Int, payloads: List) {}

重写onItemViewHolderCreated方法传入泛型TBinding,并在convert方法里执行绑定。这里暴露了一个重载方法convert(holder: BaseViewHolder, item: T, position: Int)。用过BRVAH的程序猿都知道默认的convert方法里并不提供当前item对应的position,这点不方便导致该框架被问的最多的问题之一就是“如何在convert方法里获取position” -_-! 这里直接在原来的convert方法里调用新增的重载方法并传入当前的position,这样在子类里我们重写convert方法时就可以直接获得当前的position了。同时原convert方法被设置为final类型以确保其在子类中不被重写。

点击监听扩展

BRVAH默认的setOnItemClickListener有一点不好,就是不提供当前的item,只能通过dataList[position]或adpter.getItem(position) as T来获取。前者可能需要我们将dataList设置为全局变量,后者更是需要做强制类型转换,都不是很方便。现在我们丢掉自带监听,重新实现一个能提供当前item的点击监听方法。

private var onItemClickListener: ((BaseAdapter, View, Int, T) -> Unit)? = null

private var onItemLongClickListener: ((BaseAdapter, View, Int, T) -> Boolean)? = null

private var onItemChildClickListener: ((BaseAdapter, View, Int, T) -> Unit)? = null

private var onItemChildLongClickListener: ((BaseAdapter, View, Int, T) -> Boolean)? = null

protected open fun setOnItemClick(view: View, position: Int, item: T) {

onItemClickListener?.invoke(this, view, position, item)

}

protected open fun setOnItemLongClick(view: View, position: Int, item: T): Boolean {

return onItemLongClickListener?.invoke(this, view, position, item) ?: false

}

protected open fun setOnItemChildClick(view: View, position: Int, item: T) {

onItemChildClickListener?.invoke(this, view, position, item)

}

protected open fun setOnItemChildLongClick(view: View, position: Int, item: T): Boolean {

return onItemChildLongClickListener?.invoke(this, view, position, item) ?: false

}

fun setOnItemClickListener(listener: (BaseAdapter, View, Int, T) -> Unit) {

onItemClickListener = listener

}

fun setOnItemLongClickListener(listener: (BaseAdapter, View, Int, T) -> Boolean) {

onItemLongClickListener = listener

}

fun setOnItemChildClickListener(listener: (BaseAdapter, View, Int, T) -> Unit) {

onItemChildClickListener = listener

}

fun setOnItemChildLongClickListener(listener: (BaseAdapter, View, Int, T) -> Boolean) {

onItemChildLongClickListener = listener

}

override fun bindViewClickListener(viewHolder: BaseViewHolder, viewType: Int) {

onItemClickListener?.let {

viewHolder.itemView.setOnClickListener { v ->

var position = viewHolder.adapterPosition

if (position == RecyclerView.NO_POSITION) {

return@setOnClickListener

}

position -= headerLayoutCount

setOnItemClick(v, position, getItem(position))

}

}

onItemLongClickListener?.let {

viewHolder.itemView.setOnLongClickListener { v ->

var position = viewHolder.adapterPosition

if (position == RecyclerView.NO_POSITION) {

return@setOnLongClickListener false

}

position -= headerLayoutCount

setOnItemLongClick(v, position, getItem(position))

}

}

onItemChildClickListener?.let {

for (id in getChildClickViewIds()) {

viewHolder.itemView.findViewById(id)?.let { childView ->

if (!childView.isClickable) {

childView.isClickable = true

}

childView.setOnClickListener { v ->

var position = viewHolder.adapterPosition

if (position == RecyclerView.NO_POSITION) {

return@setOnClickListener

}

position -= headerLayoutCount

setOnItemChildClick(v, position, getItem(position))

}

}

}

}

onItemChildLongClickListener?.let {

for (id in getChildLongClickViewIds()) {

viewHolder.itemView.findViewById(id)?.let { childView ->

if (!childView.isLongClickable) {

childView.isLongClickable = true

}

childView.setOnLongClickListener { v ->

var position = viewHolder.adapterPosition

if (position == RecyclerView.NO_POSITION) {

return@setOnLongClickListener false

}

position -= headerLayoutCount

setOnItemChildLongClick(v, position, getItem(position))

}

}

}

}

}

因为一并重写了长按和子控件的监听所以代码略有点长,其实只需要看onItemClickListener,setOnItemClick,setOnItemClickListener和bindViewClickListener这四个方法就行了。

首先private var onItemClickListener: ((BaseAdapter, View, Int, T) -> Unit)? = null这里onItemClickListener是一个函数对象(在kotlin里万物皆可定义为对象),具体实现在setOnItemClickListener时指定。setOnItemClick相比框架的原版方法多了一个参数item: T,以便暴露当前的item。然后重写BRVAH的bindViewClickListener方法,将原版的setOnItemLongClick方法换成我们修改版的并传入当前item。

这里顺便提一下为什么不用接口来实现监听。在java里我们通常使用接口来实现监听回调,但在kotlin里更推荐将监听接口直接定义为函数对象,因为kotlin接口不支持转换为lambda表达式,而函数对象可以(kotlin调用java接口也可以)。如果要通过接口实现同时又不舍得放弃lambda,则只能将接口写在外面的java类中。(不想多此一举的话,还是选择函数对象吧)

实现类adapter

class FruitAdapter (layoutId: Int, brId: Int, itemList: MutableList) : BaseAdapter(layoutId, brId, itemList)

一行代码就搞定了!如果需要执行其他操作,就跟用BRVAH一样重写convert方法

override fun convert(holder: BaseViewHolder, item: Fruit, position: Int) {

super.convert(holder, item, position) //别忘了调用父类方法,否则不会执行绑定

...

}

同时BaseQuickAdapter的其他功能都被保留!

扩展阅读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1、管理员登录中间件和注销

1、根据session去判断用户是否登录,登录后才可以进index首页,否则返回login页面,借助中间件 (1)修改路由 Route::group([middleware > [web,admin.login],prefix>admin,namespace>Admin], function () { //注册一个中间件admin.logi…

HTML阅读打开点击不了,如何让网页文章中的代码可以点击运行

在网页中运行代码HTML5学堂:很多代码网站当中,都会提供运行代码段功能,便于查看代码效果,那么这个是如何实现的呢?一起来看一下——如何在网页中运行代码。HTML5学堂-刘国利said:应该是在2013年的时候&…

angular-cli构建

angular-cli全称Command Line Interface 命令行界面 1使用命令 npm install -g angular-cli 安装angular-cli, 2安装完成后使用cli快速常见一个angular模板, 3ng serve启动项目 4在模板(seed/种子)的基础上进行修改 ############################## 在typescript中引用leanclou…

模仿块级作用域

模仿块级作用域 JavaScript中没有块级作用域&#xff0c;这意为着在块语句中定义的变量&#xff0c;实际上是包含在函数中而非语句中创建的。 下面的这个实例可以看出: function outputNumbers(count){for (var i0; i < count; i){alert(i);}alert(i); //count }outputNum…

html留言回复评论页面模板,HTML5实现留言和回复的页面样式

这篇文章主要介绍了用HTML5如何实现留言和回复样式,需要的朋友可以参考下具体就不做详细讲解了&#xff0c;直接上代码&#xff1a;web开发-webkfa.com*{margin:0;padding:0;-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */-webkit-t…

UVA-714 二分

把可能的进行二分判断&#xff0c;判断的时候尽量向右取&#xff0c;一直取到不能去为止&#xff0c;这样才有可能成功分割。 判断是否可以把up作为最大值的代码&#xff1a; bool judge(LL up){if(up < Big) return false; //Big是数组中最大值&#xff0c;如果up小于最大值…

html5不支持的属性,HTML5 常用语法一览(列举不支持的属性)

HTML头部标记标记描述HTML5标准定义页面中所有链接的基准URL设定显示在浏览器左上方的标题内容表明该文档是一个可用于检索的网关脚本不支持文档本身的元信息,例如查询关键词,有效期等设定CSS层叠样式表内容设定外部资源的链接页面脚本内容元信息标记属性标记描述值HTML5标准ht…

守护线程

/*守护线程&#xff08;后台线程&#xff09;:在一个进程中如果只剩下了守护线程&#xff0c;那么守护线程也会死亡。需求&#xff1a; 模拟QQ下载更新包。一个线程默认都不是守护线程。*/ public class Demo7 extends Thread {public Demo7(String name){super(name);}Overrid…

c 的word转为html5,word与html互转(1) -- word转html

使用忠告使用该方式进行xhtml到word的转换, 简单转换是可以, 但是可能并没有想象中那么满意, 转换出来的word格式并不完美, 比如目录和标题都会丢失, 标题显示看起来一样, 但是是用正文加粗和加大字号来显示的. 毕竟word是一种文档格式, 而html是一种标记性语言, 要想实现完美兼…

html5列表菜单特效,HTML5 SVG汉堡包菜单按钮分段动画特效

这是一款效果非常炫酷的HTML5 SVG汉堡包菜单按钮分段动画特效。该菜单按钮特效在用户点击汉堡包按钮时&#xff0c;按钮会分割为多段&#xff0c;并旋转变形为关闭按钮的状态。当再次点击该按钮时&#xff0c;它会逆向变形为汉堡包图标。该特效是基于Segment.js插件(一款可以只…

计算机选修课学什么,计算机专业都学什么 主要课程有什么

计算机专业的主要学习内容有什么呢&#xff0c;都开设哪些课程呢&#xff0c;下面小编为大家提供计算机专业主要学习内容&#xff0c;仅供大家参考。计算机专业主要学习内容一、数学类主要课程&#xff1a;高等数学、线性代数、离散数学、概率论、数理统计二、语言类主要课程&a…

Python学习札记(十七) 高级特性3 列表生成式

参考&#xff1a;列表生成式 Note 1.List Comprehensions&#xff0c;即列表生成式&#xff0c;是Python中内置的非常强大的list生成式。 eg.生成一个列表&#xff1a;[1*1, 2*2, ..., 10*10] 使用for...in的方法&#xff1a; #!/usr/bin/env python3L1 []for i in range(1, 1…

excel取html文本长度,excel字符长度 怎么计算excel里的字符串的长度

请教&#xff1a;在EXCEL中如何统计字符长度&#xff1f;打开excel文件&#xff0c;确定需要编辑的内容选择功能区的“公式”功能在公式中选择“LEN”功能在text中选择需要编辑的单元格 7、点击“确定” 8、系统自动计算出了单元excel中怎么判断字符串的长度在Excel中可以使用两…

Java学习之String StringBuffer StringBuilder区别

1.String&#xff1a;对象长度是不可变的&#xff0c;是线程安全。 2.StringBuffer&#xff1a;对象长度是可变的&#xff0c;是线程安全。 3.StringBuilder&#xff1a;对象长度是可变&#xff0c;不是线程安全。转载于:https://www.cnblogs.com/michaelShao/p/6372556.html

计算机找不到管理无线网络,电脑wifi密码忘了 并且找不到管理无线网络该怎么处理?...

电脑能连无线网而不能连有线网怎么办你的网卡的TCP/IP协议&#xff0c;设置了自动获取IP地址&#xff0c;然而你的局域网中不存在可以让你的机器得到IP地址的DHCP服务器。所以你的IP地址没有获取到&#xff0c;当然是受限制或无连接。解决方法是&#xff0c;为每个网卡设置一个…

Java虚拟机(JVM)默认字符集详解

Java中对字符串等进行转换字节数组时, 需要根据字符集编码来进行转换, 当不显示的指定字符集编码时(如: "测试".getBytes()), 会使用Charset.defaultCharset()获取到的字符集编码进行转换! 相关代码如下: 上面的代码可以看出, 在JVM中defaultCharset()是在初始化阶段…

计算机本地用户删除后怎么恢复,Default User文件夹被删了怎样恢复

满意答案opposities2013.06.06采纳率&#xff1a;80% 等级&#xff1a;24已帮助&#xff1a;17327人1、开机后出现“Windows 不能加载本地存储的配置文件。此问题的可能原因是安全权限不足或本地配置文件损坏。如果此问题持续存在&#xff0c;请与您的网络管理员联系。倒数3…

08-SSH综合案例:前台用户模块:注册页面的前台JS校验

这个是MyEclipse设置的问题 把设置去掉就没问题了。 你也可以在每一个input后面加个span来显示提示的信息。这些东西也要提交到后台&#xff0c;后台也是要对这些东西进行校验的。转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/6377756.html

html绘制波形图,JS实现波形图

一直想写个波线图&#xff0c;但写出来发现这是点阵组成的&#xff0c;不知道如何把线条弄的特别的平滑&#xff0c;有会的&#xff0c;求留言评论指导。1.[代码][JavaScript]代码Document.container{width:500px;height:500px;border:1px solid #DEDEDE;}.container span{widt…

sql 中on和where的区别

table a(id, type): id type ---------------------------------- 1 1 2 1 3 2 table b(id, class): id class --------------------------------- 1 1 2 2 sql语句1&#xff1a;select a.*, b.* from a left j…