如何在Kotlin中封裝RecyclerView Adapter?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
成都創(chuàng)新互聯(lián)公司專注于企業(yè)成都全網(wǎng)營銷推廣、網(wǎng)站重做改版、新平網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、html5、成都商城網(wǎng)站開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為新平等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。單類型的使用
val adapter=recyclerView.setUp(users, R.layout.item_layout, { holder, item -> var binding = DataBindingUtil.getBinding(holder.itemView) binding.nameText.text = item.name ... })
多類型的使用
recyclerView.setUP(users, listItems = *arrayOf( ListItem(R.layout.item_layout, { holder, item -> var binding = DataBindingUtil.getBinding(holder.itemView) binding?.nameText?.text = item.name ... }, { Snackbar.make(window.decorView, it.name, Snackbar.LENGTH_SHORT).show() }), ListItem(R.layout.item_layout2, { holder, item -> val nameText: TextView = holder.getView(R.id.nameText) nameText.text = item.name ... }, { }) ))
使用就是如此簡單,再來看下代碼是不是過度封裝
Adapter的基類
abstract class AbstractAdapter- constructor(protected var itemList: List
- ) : RecyclerView.Adapter
() { override fun getItemCount() = itemList.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder { val view = createItemView(parent, viewType) val viewHolder = Holder(view) val itemView = viewHolder.itemView itemView.setOnClickListener { val adapterPosition = viewHolder.adapterPosition if (adapterPosition != RecyclerView.NO_POSITION) { onItemClick(itemView, adapterPosition) } } return viewHolder } fun update(items: List - ) { updateAdapterWithDiffResult(calculateDiff(items)) } private fun updateAdapterWithDiffResult(result: DiffUtil.DiffResult) { result.dispatchUpdatesTo(this) } private fun calculateDiff(newItems: List
- ) = DiffUtil.calculateDiff(DiffUtilCallback(itemList, newItems)) fun add(item: ITEM) { itemList.toMutableList().add(item) notifyItemInserted(itemList.size) } fun remove(position: Int) { itemList.toMutableList().removeAt(position) notifyItemRemoved(position) } final override fun onViewRecycled(holder: Holder) { super.onViewRecycled(holder) onViewRecycled(holder.itemView) } protected open fun onViewRecycled(itemView: View) { } protected open fun onItemClick(itemView: View, position: Int) { } protected abstract fun createItemView(parent: ViewGroup, viewType: Int): View class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val views = SparseArray
() fun getView(viewId: Int): T { var view = views[viewId] if (view == null) { view = itemView.findViewById(viewId) views.put(viewId, view) } return view as T } } }
子類的實現(xiàn)和RecyclerView的擴展
class SingleAdapter- (items: List
- , private val layoutResId: Int, private val bindHolder: (Holder, ITEM) -> Unit) : AbstractAdapter
- (items) { private var itemClick: (ITEM) -> Unit = {} constructor(items: List
- , layoutResId: Int, bindHolder: (Holder, ITEM) -> Unit, itemClick: (ITEM) -> Unit = {}) : this(items, layoutResId, bindHolder) { this.itemClick = itemClick } override fun createItemView(parent: ViewGroup, viewType: Int): View { var view = parent inflate layoutResId if (view.tag?.toString()?.contains("layout/") == true) { DataBindingUtil.bind
(view) } return view } override fun onBindViewHolder(holder: Holder, position: Int) { bindHolder(holder, itemList[position]) } override fun onItemClick(itemView: View, position: Int) { itemClick(itemList[position]) } } class MultiAdapter - (private val items: List
- , private val bindHolder: (Holder, ITEM) -> Unit) : AbstractAdapter
- (items) { private var itemClick: (ITEM) -> Unit = {} private lateinit var listItems: Array
> constructor(items: List - , listItems: Array
>, bindHolder: (Holder, ITEM) -> Unit, itemClick: (ITEM) -> Unit = {}) : this(items, bindHolder) { this.itemClick = itemClick this.listItems = listItems } override fun createItemView(parent: ViewGroup, viewType: Int): View { var view = parent inflate getLayoutId(viewType) if (view.tag?.toString()?.contains("layout/") == true) { DataBindingUtil.bind (view) } return view } private fun getLayoutId(viewType: Int): Int { var layoutId = -1 listItems.forEach { if (it.layoutResId == viewType) { layoutId = it.layoutResId return@forEach } } return layoutId } override fun getItemViewType(position: Int): Int { return items[position].getType() } override fun onBindViewHolder(holder: Holder, position: Int) { bindHolder(holder, itemList[position]) } override fun onItemClick(itemView: View, position: Int) { itemClick(itemList[position]) } } fun - RecyclerView.setUp(items: List
- , layoutResId: Int, bindHolder: (AbstractAdapter.Holder, ITEM) -> Unit, itemClick: (ITEM) -> Unit = {}, manager: RecyclerView.LayoutManager = LinearLayoutManager(this.context)): AbstractAdapter
- { val singleAdapter by lazy { SingleAdapter(items, layoutResId, { holder, item -> bindHolder(holder, item) }, { itemClick(it) }) } layoutManager = manager adapter = singleAdapter return singleAdapter } fun
- RecyclerView.setUP(items: List
- , manager: RecyclerView.LayoutManager = LinearLayoutManager(this.context), vararg listItems: ListItem
- ): AbstractAdapter
- { val multiAdapter by lazy { MultiAdapter(items, listItems, { holder, item -> var listItem: ListItem
- ? = getListItem(listItems, item) listItem?.bindHolder?.invoke(holder, item) }, { item -> var listItem: ListItem
- ? = getListItem(listItems, item) listItem?.itemClick?.invoke(item) }) } layoutManager = manager adapter = multiAdapter return multiAdapter } private fun
- getListItem(listItems: Array
>, item: ITEM): ListItem - ? { var listItem: ListItem
- ? = null listItems.forEach { if (it.layoutResId == item.getType()) { listItem = it return@forEach } } return listItem } class ListItem
- (val layoutResId: Int, val bindHolder: (holder: AbstractAdapter.Holder, item: ITEM) -> Unit, val itemClick: (item: ITEM) -> Unit = {}) interface ListItemI { fun getType(): Int }
ok,所有核心代碼,沒有了,也不打算發(fā)布rar,要用的直接clone下來引入項目,這是最好的方式,因為不復(fù)雜,要改隨時可以改。
看上面的多類型的使用,可以發(fā)現(xiàn)它是支持普通Layout和DataBinding Layout的,這也是本庫的一個特色,不需要多余的處理。
1.普通的Layout 這樣處理
ListItem(R.layout.item_layout2, { holder, item -> val nameText: TextView = holder.getView(R.id.nameText) nameText.text = item.name }
通過Holder來操作View,里面有做緩存的。
DataBinding Layout ListItem(R.layout.item_layout, { holder, item -> var binding = DataBindingUtil.getBinding(holder.itemView) binding.nameText.text = item.name }
是不是只要自己知道是哪中Layout,對應(yīng)處理就可以了,Holder處理方式也是可以處理DataBinding Layout的,要知曉。
這里提下,可能有人會問干嘛不直接用Kotlin的Layout View 查找方法???
那樣代碼看起來是簡單,但是現(xiàn)在的Studio 對這個的支持不是很好,經(jīng)常報紅,程序員看到紅會煩躁啊!!如果還是喜歡的話實現(xiàn)也很簡單,改成View的擴展返回就可以了,可以自己動手試下哦。
因為這里只是對不變的部分進行了封裝,沒有很多華麗麗的添加頭部、腳部啥的功能,點擊事件倒是內(nèi)置了一種,當(dāng)然點擊事件還可以用ItemTouchHelper實現(xiàn),都是可以的。
這樣每次就不用寫一大串的Adaper了,是不是可以開心地泡壺茶,吹口氣了。
別的庫都可以Item復(fù)用的,你的可以嗎?
嗯嗯、、?可以的
比如
val item: (AbstractAdapter.Holder, User) -> Unit = { holder, user -> }
再比如
ListItem(R.layout.item_layout, { holder, item -> var binding = DataBindingUtil.getBinding(holder.itemView) }, {//點擊事件 Snackbar.make(window.decorView, it.name, Snackbar.LENGTH_SHORT).show() })
看完上述內(nèi)容,你們掌握如何在Kotlin中封裝RecyclerView Adapter的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!