利用lambda簡化RecyclerView.Adapter

利用lambda簡化RecyclerView.Adapter

每次出現新的列表,一般我們會新建一個類去繼承RecyclerView.Adapter然後覆寫其中方法。一次兩次還好,但很多次之後呢?你是否會不厭其煩?想必我們在實際應用中也不會只有一個或兩個列表,隨着列表的增多,我們寫了越來越多的Adapter,但其中大部分代碼是相同的,卻不能複用,同時,我相信隨着自定義的Adapter越來越多,管理也會越加複雜,這對我們程序猿來說怎麼可以忍受。所以我正好利用kotlin的lambda表達式來消除我們冗餘的代碼。
下面是自定義的Adapter,有了它我們就不需要每次再再做重複的勞動了。


class ViewAdapter<T, VH : ViewHolder>(
        @LayoutRes private val layoutResId: Int,
        val data: MutableList<T> = mutableListOf()) :
        RecyclerView.Adapter<VH>() {

    constructor(
            @LayoutRes layoutResId: Int,
            data: MutableList<T> = mutableListOf(),
            @Suppress("UNCHECKED_CAST")
            clazz: Class<VH>
    ) : this(layoutResId, data) {
        this.clazz = clazz
    }

   
    @Suppress("UNCHECKED_CAST")
    private var clazz: Class<VH> = ViewHolder::class.java as java.lang.Class<VH>
    private var cons: Constructor<VH>? = null

    @Suppress("UNCHECKED_CAST")
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        val itemView = parent.context.inflate(layoutResId, parent)
                .apply { setOnClickListener { onItemClick?.invoke(it, it.tag as Int) } }
        if (cons == null)
            //itemView: View, parent: ViewGroup, viewType: Int
            cons = clazz.getConstructor(View::class.java, ViewGroup::class.java, Int::class.java)
        return cons!!.newInstance(itemView, parent, viewType)
    }

    override fun onBindViewHolder(holder: VH, position: Int) {
        holder.itemView.tag = position
        onBind(holder, data[position])
    }

    override fun getItemCount(): Int {
        return data.size
    }

    fun setOnBindListener(listener: (VH, T) -> Unit) {
        this.onBind = listener
    }

    fun setOnItemClickListener(listener: (view: View, position: Int) -> Unit) {
        this.onItemClick = listener
    }

    fun replaceAll(list: List<T>) {
        data.clear()
        data.addAll(0, list)
        notifyDataSetChanged()
    }

    private var onItemClick: ((view: View, position: Int) -> Unit)? = null

    private lateinit var onBind: (VH, T) -> Unit
}

然後我們就可以只通過下面的方式來設置RecyclerView的Adapter了

        private lateinit var adapter: ViewAdapter<WeekLesson, ViewHolder>


        adapter = ViewAdapter(R.layout.class_schedule_item)
        adapter.setOnBindListener { viewHolder, classItem ->
           //Use your viewHolder
        }
        adapter.setOnItemClickListener { view, position -> 
            
        }
        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = adapter

這裏需要注意的是setOnItemClickListener並不是必須的,而setOnBindListener則是必須的,因爲要在onBindViewHolder的時候要回調。
ViewHolder需要實現這樣一個構造參數(itemView: View, parent: ViewGroup, viewType: Int)第一個參數是每一項的View,第二個參數在這裏即爲RecyclerView的父佈局,第三個參數爲你自己定義的ViewType。
data可以通過adapter.data訪問,我們可以在創建Adapter的時候傳入數據集合,也可以在創建之後再更新

然後就可以開開心心的寫代碼了,再也不用重複那些枯燥的操作啦。另外還有一種方式,就是通過自定義Android Studio模板代碼的方式讓IDE來幫我們自動創建並完成一些重複代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章