Kotlin 写一个通用Adapter (二)

2,105 阅读2分钟

说在前面

上次写了一个通用adapter,用的过程中,发现还是没那么方便,每次数据绑定的时候都要强转一次,bindView时也不够简洁,通过进一步学习kotlin,进行了优化,性能的话,单看二者没有多大区别,主要是在写法的简洁度上做出了改善,先放出代码


/**
 * actor 晴天 create 2019/5/17
 * 封装一个kotlin下的通用adapter
 */

class KotlinDataAdapter<T> private constructor() : RecyclerView.Adapter<KotlinDataAdapter<T>.MyViewHolder>() {

    //数据
    private var mDatalist: ArrayList<T>? = null
    //布局id
    private var mLayoutId: Int? = null
    //绑定事件的lambda放发
    private var addBindView: ((itemView: View, itemData: T) -> Unit)? = null

    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): MyViewHolder {
        val view = LayoutInflater.from(p0.context).inflate(mLayoutId!!, p0, false)
        return MyViewHolder(view)
    }

    override fun getItemCount(): Int {
        return mDatalist?.size ?: -1 //左侧为null时返回-1
    }

    override fun onBindViewHolder(p0: MyViewHolder, p1: Int) {
        addBindView?.invoke(p0.itemView, mDatalist?.get(p1)!!)
    }

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    /**
     * 建造者,用来完成adapter的数据组合
     */
    class Builder<B> {

        private var adapter: KotlinDataAdapter<B> = KotlinDataAdapter()

        /**
         * 设置数据
         */
        fun setData(lists: ArrayList<B>): Builder<B> {
            adapter.mDatalist = lists
            return this
        }

        /**
         * 设置布局id
         */
        fun setLayoutId(layoutId: Int): Builder<B> {
            adapter.mLayoutId = layoutId
            return this
        }

        /**
         * 绑定View和数据
         */
        fun addBindView(itemBind: ((itemView: View, itemData: B) -> Unit)): Builder<B> {
            adapter.addBindView = itemBind
            return this
        }

        fun create(): KotlinDataAdapter<B> {
            return adapter
        }
    }

}

使用方法如下

      val  adapter = KotlinDataAdapter.Builder<DeviceModel>()
                .setData(deviceList)
                .setLayoutId(R.layout.item_device)
                .addBindView { itemView, itemData ->
                    itemView.tv_device_name.text = if (itemData.platform.isEmpty()) "未命名" else 
                }
                .create()

看起来其实差别也不算太大哈,主要变化是在声明的时候,采用了泛型,声明时需要传入指定的数据类型,再者是,之前在addBindView得时候,需要用object:来传入对象,再在里面实现方法,这次我使用了lambda表达式的方式,addBindView的时候就可以直接传入lambda表达式,从而进一步简化了代码,代码其实很简单,想要进一步了解的可以搜索一下kotlin的lambda方法,和高阶函数的使用

 //绑定事件的lambda放发
    private var addBindView: ((itemView: View, itemData: T) -> Unit)? = null
    
    /**
    * 绑定View和数据
    */
    fun addBindView(itemBind: ((itemView: View, itemData: B) -> Unit)): Builder<B> {
        adapter.addBindView = itemBind
        return this
    }