国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

Kotlin封裝RecyclerView Adapter實(shí)例教程

2024-07-21 23:03:49
字體:
供稿:網(wǎng)友

前言

Kotlin越來越流行,在Google的推動(dòng)下發(fā)展的很迅猛,現(xiàn)在的項(xiàng)目大多使用上了Kotlin,其簡(jiǎn)練的語法糖確實(shí)能減少不少代碼。

Adapter的封裝GitHub上有很多了,但大多數(shù)封裝的太好了,是的,使用太簡(jiǎn)單了,使用簡(jiǎn)單、封裝力度大就導(dǎo)致靈活性和代碼復(fù)雜性上升,誰用誰知道,當(dāng)然也有封裝簡(jiǎn)單的。

這里我借助Kotlin的簡(jiǎn)單語法再次操刀封裝了一下。

先看下使用

單類型的使用

val adapter=recyclerView.setUp(users, R.layout.item_layout, { holder, item ->   var binding = DataBindingUtil.getBinding<ItemLayoutBinding>(holder.itemView)   binding.nameText.text = item.name   ...  })

多類型的使用

recyclerView.setUP(users,    listItems = *arrayOf(      ListItem(R.layout.item_layout, { holder, item ->       var binding = DataBindingUtil.getBinding<ItemLayoutBinding>(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       ...      }, {      })    ))

使用就是如此簡(jiǎn)單,再來看下代碼是不是過度封裝

Adapter的基類

abstract class AbstractAdapter<ITEM> constructor(protected var itemList: List<ITEM>) : RecyclerView.Adapter<AbstractAdapter.Holder>() { 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<ITEM>) {  updateAdapterWithDiffResult(calculateDiff(items)) } private fun updateAdapterWithDiffResult(result: DiffUtil.DiffResult) {  result.dispatchUpdatesTo(this) } private fun calculateDiff(newItems: List<ITEM>) =   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<View>()  fun <T : View> getView(viewId: Int): T {   var view = views[viewId]   if (view == null) {    view = itemView.findViewById(viewId)    views.put(viewId, view)   }   return view as T  } }}

子類的實(shí)現(xiàn)和RecyclerView的擴(kuò)展

class SingleAdapter<ITEM>(items: List<ITEM>,       private val layoutResId: Int,       private val bindHolder: (Holder, ITEM) -> Unit) : AbstractAdapter<ITEM>(items) { private var itemClick: (ITEM) -> Unit = {} constructor(items: List<ITEM>,    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<ViewDataBinding>(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<ITEM : ListItemI>(private val items: List<ITEM>,          private val bindHolder: (Holder, ITEM) -> Unit) : AbstractAdapter<ITEM>(items) { private var itemClick: (ITEM) -> Unit = {} private lateinit var listItems: Array<out ListItem<ITEM>> constructor(items: List<ITEM>,    listItems: Array<out ListItem<ITEM>>,    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<ViewDataBinding>(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 <ITEM> RecyclerView.setUp(items: List<ITEM>,        layoutResId: Int,        bindHolder: (AbstractAdapter.Holder, ITEM) -> Unit,        itemClick: (ITEM) -> Unit = {},        manager: RecyclerView.LayoutManager = LinearLayoutManager(this.context)): AbstractAdapter<ITEM> { val singleAdapter by lazy {  SingleAdapter(items, layoutResId, { holder, item ->   bindHolder(holder, item)  }, {   itemClick(it)  }) } layoutManager = manager adapter = singleAdapter return singleAdapter}fun <ITEM : ListItemI> RecyclerView.setUP(items: List<ITEM>,           manager: RecyclerView.LayoutManager = LinearLayoutManager(this.context),           vararg listItems: ListItem<ITEM>): AbstractAdapter<ITEM> { val multiAdapter by lazy {  MultiAdapter(items, listItems, { holder, item ->   var listItem: ListItem<ITEM>? = getListItem(listItems, item)   listItem?.bindHolder?.invoke(holder, item)  }, { item ->   var listItem: ListItem<ITEM>? = getListItem(listItems, item)   listItem?.itemClick?.invoke(item)  }) } layoutManager = manager adapter = multiAdapter return multiAdapter}private fun <ITEM : ListItemI> getListItem(listItems: Array<out ListItem<ITEM>>, item: ITEM): ListItem<ITEM>? { var listItem: ListItem<ITEM>? = null listItems.forEach {  if (it.layoutResId == item.getType()) {   listItem = it   return@forEach  } } return listItem}class ListItem<ITEM>(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下來引入項(xiàng)目,這是最好的方式,因?yàn)椴粡?fù)雜,要改隨時(shí)可以改。

看上面的多類型的使用,可以發(fā)現(xiàn)它是支持普通Layout和DataBinding Layout的,這也是本庫的一個(gè)特色,不需要多余的處理。

1.普通的Layout 這樣處理

ListItem(R.layout.item_layout2, { holder, item ->       val nameText: TextView = holder.getView(R.id.nameText)       nameText.text = item.name      }

通過Holder來操作View,里面有做緩存的。

DataBinding LayoutListItem(R.layout.item_layout, { holder, item ->       var binding = DataBindingUtil.getBinding<ItemLayoutBinding>(holder.itemView)       binding.nameText.text = item.name      }

是不是只要自己知道是哪中Layout,對(duì)應(yīng)處理就可以了,Holder處理方式也是可以處理DataBinding Layout的,要知曉。

這里提下,可能有人會(huì)問干嘛不直接用Kotlin的Layout View 查找方法???

那樣代碼看起來是簡(jiǎn)單,但是現(xiàn)在的Studio 對(duì)這個(gè)的支持不是很好,經(jīng)常報(bào)紅,程序員看到紅會(huì)煩躁啊!!如果還是喜歡的話實(shí)現(xiàn)也很簡(jiǎn)單,改成View的擴(kuò)展返回就可以了,可以自己動(dòng)手試下哦。

因?yàn)檫@里只是對(duì)不變的部分進(jìn)行了封裝,沒有很多華麗麗的添加頭部、腳部啥的功能,點(diǎn)擊事件倒是內(nèi)置了一種,當(dāng)然點(diǎn)擊事件還可以用ItemTouchHelper實(shí)現(xiàn),都是可以的。

這樣每次就不用寫一大串的Adaper了,是不是可以開心地泡壺茶,吹口氣了。

別的庫都可以Item復(fù)用的,你的可以嗎?

嗯嗯、、?可以的

比如

val item: (AbstractAdapter.Holder, User) -> Unit = { holder, user ->  }

再比如

ListItem(R.layout.item_layout, { holder, item ->       var binding = DataBindingUtil.getBinding<ItemLayoutBinding>(holder.itemView)      }, {//點(diǎn)擊事件       Snackbar.make(window.decorView, it.name, Snackbar.LENGTH_SHORT).show()      })

是不是一樣可以的 只要定義到一個(gè)地方 然后設(shè)置進(jìn)去就可以了,復(fù)用也是難不倒它的。只能說Kotlin語法大法好。

好了,這個(gè)庫就介紹到這里了,謝謝大家。

代碼地址

參考鏈接

靈感來自下面這位大神,但是我基本重寫了

https://github.com/armcha/Kadapter

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到kotlin教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 天长市| 肥城市| 中牟县| 平塘县| 余庆县| 项城市| 雅安市| 安化县| 秀山| 花垣县| 南昌市| 枞阳县| 南充市| 开平市| 莱芜市| 北宁市| 晋江市| 灌南县| 富平县| 阳东县| 西城区| 昌邑市| 宁陵县| 济南市| 哈密市| 柳河县| 北海市| 梁平县| 石嘴山市| 仲巴县| 大竹县| 安图县| 黑龙江省| 那坡县| 英山县| 三明市| 阿勒泰市| 神农架林区| 惠水县| 新安县| 丰顺县|