欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Kotlin封裝RecyclerView Adapter實例教程

 更新時間:2018年08月06日 12:03:46   作者:驀然地執(zhí)著  
這篇文章主要給大家介紹了關(guān)于Kotlin封裝RecyclerView Adapter的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

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

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

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

先看下使用

單類型的使用

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
       ...
      }, {

      })
    ))

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

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
  }
 }
}

子類的實現(xiàn)和RecyclerView的擴展

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下來引入項目,這是最好的方式,因為不復(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<ItemLayoutBinding>(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)置了一種,當然點擊事件還可以用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<ItemLayoutBinding>(holder.itemView)
      }, {//點擊事件
       Snackbar.make(window.decorView, it.name, Snackbar.LENGTH_SHORT).show()
      })

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

好了,這個庫就介紹到這里了,謝謝大家。

代碼地址

參考鏈接

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

https://github.com/armcha/Kadapter

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 詳解Android中PopupWindow在7.0后適配的解決

    詳解Android中PopupWindow在7.0后適配的解決

    本篇文章主要介紹了詳解Android中PopupWindow在7.0后適配的解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Android中簡單的電話管理與短信管理App編寫實例

    Android中簡單的電話管理與短信管理App編寫實例

    這篇文章主要介紹了Android中簡單的電話管理與短信管理App編寫實例,包括監(jiān)聽電話的呼叫狀態(tài)以及短信群發(fā)聯(lián)系人選擇等基本功能的實現(xiàn),代碼突出要點,需要的朋友可以參考下
    2016-04-04
  • 一分鐘快速定位Android啟動耗時問題

    一分鐘快速定位Android啟動耗時問題

    做開發(fā)除了實現(xiàn)功能,還要注重優(yōu)化,性能優(yōu)化包括的東西還是非常多的,下面這篇文章主要給大家介紹了關(guān)于如何通過一分鐘快速定位Android啟動耗時問題的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • Android Notification的多種用法總結(jié)

    Android Notification的多種用法總結(jié)

    這篇文章主要介紹了Android Notification的多種用法總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android Studio中CodeStyle模板的配置方式

    Android Studio中CodeStyle模板的配置方式

    這篇文章主要介紹了Android Studio中CodeStyle模板的配置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android Webview與ScrollView的滾動兼容及留白處理的方法

    Android Webview與ScrollView的滾動兼容及留白處理的方法

    本篇文章主要介紹了Android Webview與ScrollView的滾動兼容及留白處理的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Material Design系列之自定義Behavior支持所有View

    Material Design系列之自定義Behavior支持所有View

    這篇文章主要為大家詳細介紹了Material Design系列之自定義Behavior支持所有View,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android圓角頭像工具類詳解

    Android圓角頭像工具類詳解

    這篇文章主要為大家詳細介紹了Android圓角頭像工具類,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Android 使用Canvas在圖片上繪制文字的方法

    Android 使用Canvas在圖片上繪制文字的方法

    下面小編就為大家分享一篇Android 使用Canvas在圖片上繪制文字的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android WebView輸入框被檔問題升級解析

    Android WebView輸入框被檔問題升級解析

    這篇文章主要為大家介紹了Android WebView輸入框被檔問題升級解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02

最新評論