Kotlin 寫一個通用Adapter (二)

晴天大帥逼發表於2019-05-17

說在前面

上次寫了一個通用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
    }
複製程式碼

相關文章