传统的RecyclerView用法:
- 继承
RecyclerView.Adapter
实现getItemCount()
,createViewHolder()
,onBindViewHolder()
等方法。 - 继承
RecyclerView.ViewHolder
实现数据绑定等。 - 添加点击事件的接口。
- 如果需要
DiffUtil
,还得实现自己的ItemCallback
,然后整合进Adapter。 - 选择LayoutManger,并调用
recyclerView.setLayoutManager
。 - 实例化Adapter,并调用
recyclerView.setAdapter
。 - 实现点击事件的接口。
- 更新数据时调用
adapter.notifyDataChanged()
等方法,使用ListAdapter
时调用submitList
这个过程相比于要被替代的ListView来说不仅没有简化,还变得更复杂了。猜测这也是RecylerView虽然强大,但却一直没有彻底代替ListView等老组件的原因之一。
后来Jetpack Compose出来后,看到LazyColumn的写法如此简洁:
LazyColumn {
items(itemsList) {
Text("Item is $it")
}
item {
Text("Single item")
}
itemsIndexed(itemsIndexedList) { index, item ->
Text("Item at index $index is $item")
}
}
当时也并没有什么想法。。。后来看到了sqaure/recycler库配置RecyclerView的方式:
val recycler = Recycler.create<ItemType>(context, id = R.id.myrecycler) {
...
row<I, S, V> {
forItemsWhere { subitem -> ...boolean... }
create(R.layout.my_layout) {
// you can get references to sub-elements inside view
val subView = view.findViewById(...)
bind { subItem ->
// assign values from subItem to view or sub-elements
}
}
...more row options...
}
}
完全省略了定义Adapter的步骤,但感觉仍然还是有些复杂。那时萌生了一个想法:能不能把LazyColumn那套定义方式带给RecyclerView呢?于是就有了下面这部分。
LazyRecycler
LazyRecycler
使用和LazyColumn
相似的方式来写RecylcerView,把Adapter
,LayoutManager
,DiffUtil
点击事件等定义全部放到一个代码块中:
LazyRecycler(recyclerView, spanCount = 3) {
// 多种view type支持
item(R.layout.header, Unit) {}
items(listOfNews) { binding: ItemNewsBinding, news ->
// 绑定
}.clicks { view, item ->
// 点击事件
}.spanSize { position ->
if (position % 3 == 0) 3 else 1
}.differ {
areItemsTheSame { oldItem, newItem ->
oldItem.id == newItem.id
}
areContentsTheSame { oldItem, newItem ->
oldItem.title == newItem.title && ...
}
}
item(R.layout.footer, Unit) {}
}
相比cycler的layout id还支持ViewBinding
,不用在bind外边findViewById
了。
为了体验更加接近Compose的LazyColumn,还支持Flow
, LiveData
, RxJava的Observable
作为数据源:
val source: Flow<List<Item>> = ...
...
items(source) { ... }
调用recycler.observeChanges()
观察数据变化,自动更新Adapter。
使用
implementation 'io.github.dokar3:lazyrecycler:0.1.1'
// Flow支持
implementation 'io.github.dokar3:lazyrecycler-flow:0.1.1'
// LiveData支持
implementation 'io.github.dokar3:lazyrecycler-livedata:0.1.1'
// RxJava支持
implementation 'io.github.dokar3:lazyrecycler-rxjava3:0.1.1'
创建LazyRecycler
:
// 传入RecyclerView
LazyRecycler(recyclerView) {
...
}
// attachTo()
val lazyRecycler = LazyRecycler {
...
}
lazyRecycler.attachTo(recyclerView)
创建item
/ items
:
item(R.layout.header, Unit) { view ->
val title: TextView = view.findViewById(...)
bind {
title.text = ...
}
}
item<HeaderBinding> { ... }
items(R.layout.item_news, newsList) { view ->
val title: TextView = view.findViewById(...)
val cover: ImageView = view.findViewById(...)
...
bind { news ->
title.text = news.title
cover.load(news.cover)
...
}
}
items(newsList) { binding: ItemNewsBinding, news ->
binding.title.text = news.title
binding.cover.load(news.cover)
...
}
各类配置:
items(...) {
...
}.clicks { view, news ->
// 点击事件
}.longClicks { view, news ->
// 长按事件
true
}.spanSize { position
// SpanSizeLookup.getSpanSize的映射
1
}.differ {
// DiffUtil.ItemCallback的映射
areItemsTheSame { old, new -> ... }
areContentsTheSame { old, new -> ... }
}.subSection(sectionBreakingNews) { news, position ->
// 同数据源不同item type
news.priority == ...
}
...
更多使用请查看Github:
https://github.com/dokar3/LazyRecycler
相关链接:
网友评论