原创文章,转载请联系作者
前言
这是Kotlin实践日记的第一章,使用Kotlin构建一个,使用方便、多功能的Recyclerview适配器——AcrobatAdapter
。
AcrobatAdapter
让开发者专注于Item的配置,包括Item
的UI和数据显示,以及单击、双击、长按事件【且不会影响子View的事件传递】。而且不仅仅是单Item Style
列表,还是多Item Style
列表,AcrobatAdapter
的使用都是一样方便简单。
AcrobatAdapter
的设计灵感来自于夜叉,我的函数名称也沿用夜叉的函数名,因为itemDSL
这个名称是在太贴切了。夜叉这个项目是针对Recyclerview整体来构建,推荐小可爱们去看看。
GitHub
链接放在文章底部哦。
下面将展示使用文档。
使用文档
普通列表
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item" + d
}
}
}.setData(数据源)
recycler_view.adapter = acrobatAdapter
哒哒,以上代码就成功构建了一个列表
resId()函数绑定Item的布局ID
showItem函数内,渲染数据,d表示此项Item对应数据,会根据适配器泛型自动转换。pos为Item的position,view是Item的布局View。而且Kotlin支持使用Id代表控件,再也不用写findViewById啦!
最后,适配器的setData方法内置了DiffUtils,会对比新旧数据,这样在数据刷新时Recyclerview会有默认动画展示。让交互更加平滑。
如果开发者在项目中,有好几个界面的Item完全一样,那岂不是还要写几套代码?完全不用担心,Item也支持复用。
首先Item相关类,继承AcrobatItem
。
class Test : AcrobatItem<Int>() {
override fun showItem(d: Int, pos: Int, view: View) {
view.item_tv.text = "共用Item" + d
}
override fun getResId(): Int = R.layout.item_test
}
在适配器中:
val acrobatAdapter = AcrobatAdapter<Int> {
item {
Test()
}
}.setData(数据源)
recycler_view.adapter = acrobatAdapter
让你的Item继承
AcrobatItem
即可。这样再多的界面复用Item也完全可行,但要注意的一点是:Item的数据类型必须一致。
多Item样式可以咩?当然可以啦!
多item样式的话,写多个ItemDSL即可!每一个ItemDSL
就代表一种独有的Item样式。同理,每调用一次item
,也就多一种Item样式。
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item: " + d
}
isMeetData { d, pos -> pos == 1 }
}
itemDSL {
resId(R.layout.item_test1)
showItem { d, pos, view ->
view.item_tv.text = "cece: " + d
}
isMeetData { d, pos -> pos != 1 }
}
}.setData(数据源)
recycler_view.adapter = acrobatAdapter
isMeetData函数两个参数为数据和position。用这两个参数来判断此Item在哪个位置、什么条件展示。譬如示例代码,position为1时是一个样式,不为1时是另一种样式。但要注意,所有的Item的isMeetData的条件都是互斥的噢。否则会抛出异常。
嗯……Recyclerview没有默认的Item点击事件怎么办?没问题,AcrobatAdapter
替你搞定。每个Item不但有单击click
,还附带了双击DoubleTap
和长按LongPress
事件。而且完全不会影响Item布局View内部childView的事件。
- 每种Item都可以绑定自己独有的三个事件
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item: " + d
}
onClick {
toastS("单击")
}
onDoubleTap {
toastS("双击")
}
longPress {
toastS("长按")
}
}
itemDSL {
resId(R.layout.item_test1)
showItem { d, pos, view ->
view.item_tv1.text = "另一种样式" + d
}
isMeetData { d, pos -> pos == 1 }
onClick {
toastS("单击另一种Item")
}
onDoubleTap {
toastS("双击另一种Item")
}
longPress {
toastS("长按另一种Item")
}
}
}.setData(数据源)
三个事件都是单独绑定Item的样式的!当使用多Item样式列表时,再也不用在click事件中,写很多的条件判断了!
AcrobatAdapter
不但支持Item绑定事件,也支持Adapter外部绑定事件。但这样就需要开发者,在外部事件里区分多Item样式了。
- 适配器持有Item事件,使用
AcrobarAdapter
的bindEvent()
函数
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item: " + d
}
isMeetData { d, pos -> pos != 1 }
}
}.setData(data).bindEvent {
onClick {
toastS("外部单击")
}
onDoubleTap {
toastS("外部双击")
}
longPress {
toastS("外部长按")
}
}
还有几个使用的小Tip
- ItemDSl的
onViewCreated(parent,view)
函数
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item: " + d
}
onViewCreate { parent, view ->
作一些和数据无关的UI操作,譬如view设置为圆形
或者EditText的addTextChangedListener
}
}
}
showItem()函数是绑定在适配器的onBingViewHolder函数里的,触发会比较频繁。如果在
showItem
内做一些UI操作,会比较浪费性能.onViewCreated
函数是绑定在适配器的onCreateViewHolder
函数内
- 刷新单个Item布局
Recyclerview如果需要刷新Item的话,不建议使用notifyItemChanged(int position)
方法,因为这个方法会刷新整个Item的视图。在视觉上的直观体现就是,Item会闪烁。所以建议使用如下方法刷新Item:
notifyItemChanged(int position, Object payload)
使用上面这个方法,不会重绘整个View的视图。
val acrobatAdapter = AcrobatAdapter<Int> {
itemDSL {
resId(R.layout.item_test)
showItem { d, pos, view ->
view.item_tv.text = "数据Item: " + d
}
showItemPayload { d, pos, view, payloads ->
刷新Item的某个特定的ChildView。
譬如在某个Item刷新进度条。下面为伪代码
view.progreess_bar.setProgress(100%)
}
}
}
下面简单做一下效果展示:
使用notifyItemChanged(int position)
和showItem
刷新布局
使用notifyItemChanged(int position, Object payload)
和showItemPayload
刷新布局
效果对比,一目了然。
结语
AcrobatAdapter,链接在此,大家要是喜欢的话不妨点个star吧。
Kotlin已成为Android开发的官方语言,不管工作上用得到用不到,大家了解一二还是有必要的。毕竟这个时代变化的太快了。
以上