利用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来帮我们自动创建并完成一些重复代码。

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