ConcatAdapter
多个adapter 根据一定的顺序拼接
MutiType 类型实现
实现方案
- 第三方库 com.chad.library.adapter[http://www.recyclerview.org/]
- ConcatAdapter
- List<T> 包含itemType,在RecyclerView.Adapter 中重写getItemViewType 实现
已实现此功能实现对比
List<T> | MultiItemEntity/Header&FooterView | ConcatAdapter | |
---|---|---|---|
实现难易程度 | ✅ | ❌ | ✅ |
代码量 | 紧簇 | 紧簇阅读性高 | 相对冗余 |
跨平台 | ✅ | ❌ | ❌ |
可扩展性 | ✅ | ✅ | ✅ |
跨平台类似 kmm 不同类型终端数据在非平台相关处维护。
ConcatAdapter 实现
导入
implementation("androidx.recyclerview:recyclerview:1.2.1")
初始化
val config = ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build()
val concatAdapter = ConcatAdapter(config, imageAdapter2, titleAdapter2, specAdapter2, featureAdapter2)
// 設定 recyclerview
binding.productRecyclerview.apply {
layoutManager = LinearLayoutManager(
this@ProductActivity,
LinearLayoutManager.VERTICAL,
false
)
// isNestedScrollingEnabled = false
adapter = concatAdapter
}
参考
https://github.com/foxtsai2333/ConcatAdapterDemo.git
优化
优化 Adapter
import android.annotation.SuppressLint
import android.content.Context
import android.view.*
import androidx.annotation.LayoutRes
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
abstract class BindableViewHolder2<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(item: T)
}
fun <T> List<T>.adapt(
context: Context,
@LayoutRes itemId: Int,
bindCall: View.(T) -> Unit
) = object : RecyclerView.Adapter<BindableViewHolder2<T>>() {
// Inflates the item views
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindableViewHolder2<T> {
val itemView = LayoutInflater.from(context).inflate(itemId, parent, false)
return object : BindableViewHolder2<T>(itemView) {
override fun bind(item: T) = itemView.bindCall(item)
}
}
override fun getItemCount(): Int = size
override fun onBindViewHolder(holder: BindableViewHolder2<T>, position: Int) =
holder.bind(get(position))
}
open class ConcatBindableAdapter3<T : Any>(private val itemLayoutViewId: Int, private var data: MutableList<T>, bindCall: View.(T, Int) -> Unit) :
GenericBindableAdapter<T>(
itemLayoutViewId, data, bindCall
) {
override fun getItemViewType(position: Int): Int {
return itemLayoutViewId
}
override fun getItemCount(): Int {
return data.size
}
}
//https://github.com/LRacoci/CoronaTracker/blob/b7b63677f53e6b4c3f7374d6858d0679ddef3c9a/app/src/main/java/com/github/coronatracker/ui/main/MainFragment.kt
open class GenericBindableAdapter<T : Any>(
private var itemLayoutViewId: Int,
private var data: MutableList<T>,
private var bindCall: View.(T, Int) -> Unit
) :
RecyclerView.Adapter<BindableViewHolder3<T>>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindableViewHolder3<T> {
val layoutInflater = LayoutInflater.from(parent.context)
val itemView = layoutInflater.inflate(itemLayoutViewId, parent, false)
return object : BindableViewHolder3<T>(itemView) {
override fun onBind(item: T, pos: Int) {
itemView.bindCall(item, pos)
}
}
}
override fun onBindViewHolder(holder: BindableViewHolder3<T>, position: Int) {
holder.bind(position, data[position])
}
override fun getItemCount() = data.size
@SuppressLint("NotifyDataSetChanged")
fun notifyDataSetChanged(list: List<T>) {
data.clear()
data.addAll(list)
notifyDataSetChanged()
}
@SuppressLint("NotifyDataSetChanged")
fun notifyDataSetCleared() {
data.clear()
notifyDataSetChanged()
}
}
abstract class BindableViewHolder3<T : Any>(itemView: View) :
RecyclerView.ViewHolder(itemView) {
fun bind(pos: Int, item: T) {
onBind(item, pos)
}
abstract fun onBind(item: T, pos: Int)
}
使用
ConcatBindableAdapter3(R.layout.listitem_product_image, image.toMutableList()) { item, pos ->
Log.e("mgg", "onBindViewHolder: fail to get image resource id from name")
}