個(gè)人原創(chuàng)淹仑,轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/14ab0ebea1a4
RecyclerView寫(xiě)多了骂铁,就對(duì)重復(fù)的adapter感到厭煩,尤其是用上databinding后重復(fù)代碼相當(dāng)多彩倚,于是干脆抽取出來(lái)寫(xiě)個(gè)供其他adapter繼承的通用的BaseAdapter堵未。廢話不多說(shuō)直接上代碼:
BaseAdapter
...
//兩個(gè)泛型,T代表item的model類型即itemList的bean類型赂苗,TBinding代表itemLayout對(duì)應(yīng)生成的XXXBinding類愉耙,比如itemLayout是fruit_item.xml,對(duì)應(yīng)的就是FruitItemBinding
//兩個(gè)參數(shù)itemList對(duì)應(yīng)具體要顯示的arrayList拌滋,brId則對(duì)應(yīng)itemLayout里相應(yīng)variable的變量名朴沿,比如variable的name是fruit,brId就是BR.fruit
abstract class BaseAdapter<T, TBinding: ViewDataBinding>(private val itemList: List<T>,
private val brId: Int) : RecyclerView.Adapter<BaseAdapter<T, TBinding>.ViewHolder>() {
protected var mContext: Context? = null
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
lateinit var binding: TBinding
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
if (mContext == null) {
mContext = parent.context
}
//因?yàn)門(mén)Binding的具體類型不確定败砂,這里只能用DataBindingUtil.inflate()赌渣,而不能用XXXBinding.inflate()
val binding: TBinding = DataBindingUtil.inflate(LayoutInflater.from(mContext), getLayoutId(), parent, false)
val holder = ViewHolder(binding.root)
holder.binding = binding
return holder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.setVariable(brId, itemList[position])
//立即執(zhí)行綁定,在對(duì)view變化時(shí)效敏感的地方常用昌犹,不加這句有可能出現(xiàn)itemView更新滯后坚芜、閃爍等問(wèn)題
holder.binding.executePendingBindings()
}
override fun getItemCount(): Int {
return itemList.size
}
//獲取具體子adapter對(duì)應(yīng)的itemLayoutId
abstract fun getLayoutId(): Int
}
代碼注釋說(shuō)的很詳細(xì)了,除了基本的顯示功能外斜姥,只重寫(xiě)了一個(gè)常用的getItemCount()
货岭。下面我們來(lái)看看具體的子類adapter:
FruitAdapter
package com.zerlings.gabeisfaker.ui.main
...
class FruitAdapter (itemList: List<Fruit>, brId: Int) : BaseAdapter<Fruit, FruitItemBinding>(itemList, brId) {
override fun getLayoutId(): Int {
return R.layout.fruit_item //item對(duì)應(yīng)的layoutId
}
}
是不是超級(jí)簡(jiǎn)單!省掉了不少重復(fù)的代碼疾渴!當(dāng)然這只包含了最基本的代碼千贯,通常我們還需要做一些擴(kuò)展功能,比如點(diǎn)擊事件:
var onItemClickListener: OnItemClickListener? = null
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
holder.itemView.setOnClickListener { v -> onItemClickListener?.onItemClick(v, position) }
}
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
}
以及添加表頭:
companion object {
private const val TYPE_HEADER = 1
private const val TYPE_NORMAL = 0
}
var headerView: View? = null
set(headerView) {
field = headerView
notifyItemInserted(0)
}
override fun getItemViewType(position: Int): Int {
return if (position == 0 && headerView != null) {
//第一個(gè)item應(yīng)該加載Header
TYPE_HEADER
} else {
TYPE_NORMAL
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return if (viewType == TYPE_HEADER) ViewHolder(headerView!!) else super.onCreateViewHolder(parent, viewType)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if (getItemViewType(position) == TYPE_NORMAL) super.onBindViewHolder(holder, position)
}
最后完整的FruitAdapter:
...
class FruitAdapter (itemList: List<Fruit>, brId: Int) : BaseAdapter<Fruit, FruitItemBinding>(itemList, brId) {
companion object {
private const val TYPE_HEADER = 1
private const val TYPE_NORMAL = 0
}
var onItemClickListener: OnItemClickListener? = null
var headerView: View? = null
set(headerView) {
field = headerView
notifyItemInserted(0)
}
override fun getItemViewType(position: Int): Int {
return if (position == 0 && headerView != null) {
//第一個(gè)item應(yīng)該加載Header
TYPE_HEADER
} else {
TYPE_NORMAL
}
}
override fun getLayoutId(): Int {
return R.layout.fruit_item //item對(duì)應(yīng)的layoutId
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return if (viewType == TYPE_HEADER) ViewHolder(headerView!!) else super.onCreateViewHolder(parent, viewType)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
if (getItemViewType(position) == TYPE_NORMAL) {
super.onBindViewHolder(holder, position)
holder.itemView.setOnClickListener { v -> onItemClickListener?.onItemClick(v, position) }
}
}
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
}
}
這個(gè)FruitAdapter只擴(kuò)展了添加header和點(diǎn)擊監(jiān)聽(tīng)兩個(gè)常用功能搞坝,有更多需求可繼續(xù)擴(kuò)展搔谴,這里就不再深入了。
至于具體的Fruit.class類和fruit_item.xml是什么樣桩撮,已經(jīng)不重要了敦第。