美文网首页Android开发Android开发经验谈Android开发
使用kotlin和databinding简单封装adapter

使用kotlin和databinding简单封装adapter

作者: 刚刚了然 | 来源:发表于2018-11-21 17:02 被阅读11次

    实现非常简单,主要运用了databinding的特性实现,使用非常简单
    https://github.com/TianGuisen/KtBindAdapter
    使用方法
    item布局中必须这样写,name="item",否则baseAdapter中BR.item会报错无法使用

    <data>
            <variable
                name="item"
                type="绑定的实体类"></variable>
    </data>
    

    创建adapter

    //单type,直接创建SimpleAdapter即可,没有item子view的点击事件
    val testAdapter = SimpleAdapter(listData, R.layout.item_sigle1)
    
    //多type
    val itemInfos = mutableListOf<MultiItem<ItemInfo>>()
    val multiAdapter = SimpleMultiAdapter(itemInfos)
    //添加布局
    multiAdapter.addItemType(TYPE0, R.layout.item_type0)
    multiAdapter.addItemType(TYPE1, R.layout.item_type1)
    //
    multiAdapter.setOnItemClickLisener { multiItem: MultiItem<ItemInfo>, view: View, i: Int ->
        ToastUtil.normal("点击的是item:" + multiItem + "  位置:" + i)
    }
    

    实现

    
    abstract class BaseAdapter<E : Any, VB : ViewDataBinding> internal constructor(datas: MutableList<E>) : RecyclerView.Adapter<BindViewHolder<VB>>() {
        internal var mDatas: MutableList<E> = datas
        internal var itemClickLisener: OnItemClickLisener<E>? = null
        internal var childClickLisener: OnChildClickLisener<E>? = null
        internal var itemLongClickLisener: OnItemLongClickLisener<E>? = null
    
    
        fun setChildClickLisener(function: (E, View, Int) -> Unit) {
            this.childClickLisener = object : OnChildClickLisener<E> {
                override fun childClick(bean: E, view: View, position: Int) {
                    function(bean, view, position)
                }
            }
        }
    
        fun setOnItemClickLisener(itemClickLisener: OnItemClickLisener<E>) {
            this.itemClickLisener = itemClickLisener
        }
    
        fun setOnItemClickLisener(function: (E, View, Int) -> Unit) {
            this.itemClickLisener = object : OnItemClickLisener<E> {
                override fun itemClick(bean: E, view: View, position: Int) {
                    function(bean, view, position)
                }
            }
        }
    
        fun setItemLongClickLisener(function: (E, View, Int) -> Unit) {
            this.itemLongClickLisener = object : OnItemLongClickLisener<E> {
                override fun itemLongClick(bean: E, view: View, position: Int) {
                    function(bean, view, position)
                }
            }
        }
    
        interface OnItemClickLisener<E> {
            fun itemClick(bean: E, view: View, position: Int)
        }
    
        interface OnChildClickLisener<E> {
            fun childClick(bean: E, view: View, position: Int)
        }
    
        interface OnItemLongClickLisener<E> {
            fun itemLongClick(bean: E, view: View, position: Int)
        }
    
        override fun onBindViewHolder(holder: BindViewHolder<VB>, position: Int) {
            val bean = mDatas[position]
            val itemView = holder.binding.getRoot()
            if (itemClickLisener != null) {
                itemView.setOnClickListener {
                    itemClickLisener!!.itemClick(bean, holder.binding.getRoot(), position)
                }
            }
            decorator(bean, holder, position)
            //如果是BaseMultiAdapter需要处理一下
            if (mDatas[position] is MultiItem<*>) {
                val pinnedHeaderEntity = mDatas[position] as MultiItem<*>
                holder.binding.setVariable(item, pinnedHeaderEntity.data)
            } else {
                holder.binding.setVariable(item, mDatas[position])
            }
            holder.binding.executePendingBindings()
        }
    
        abstract fun decorator(bean: E, holder: BindViewHolder<VB>, position: Int)
    
        open fun remove(position: Int) {
            mDatas.removeAt(position)
            notifyItemRemoved(position)
        }
    
        open fun clear() {
            mDatas.clear()
            notifyDataSetChanged()
        }
    
        override fun getItemCount(): Int {
            return mDatas.size
        }
    
    }
    
    /**
     * 单type
     * 如果item内容填充较复杂,无法在item的xml中完成,需要在decorator完成填充,就使用这个
     * 或者需要子view的点击事件使用这个
     */
    open abstract class BaseSigleAdapter<E : Any, VB : ViewDataBinding> : BaseAdapter<E, VB> {
    
        private var layoutId: Int = 0
    
        constructor(datas: MutableList<E>, layoutId: Int) : super(datas) {
            this.layoutId = layoutId
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindViewHolder<VB> {
            val binding = DataBindingUtil.inflate<VB>(LayoutInflater.from(parent.context), layoutId, parent, false)
            return BindViewHolder(binding.root, binding)
        }
    
        fun add(data: E) {
            mDatas.add(data)
            notifyDataSetChanged()
        }
    
        fun add(position: Int, data: E) {
            mDatas.add(position, data)
            notifyDataSetChanged()
        }
    
        fun set(data: List<E>) {
            mDatas.clear()
            addAll(data)
        }
    
        fun addAll(data: List<E>) {
            mDatas.addAll(data)
            notifyDataSetChanged()
        }
    }
    
    /**
     * 多type
     * 如果item内容填充较复杂,无法在item的xml中完成,需要在decorator完成填充,就使用这个
     * 或者需要子view的点击事件使用这个
     */
    open abstract class BaseMultiAdapter<E : Any> : BaseAdapter<MultiItem<E>, ViewDataBinding> {
        constructor(data: MutableList<MultiItem<E>>) : super(data)
    
        private val layouts: SparseIntArray = SparseIntArray()
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindViewHolder<ViewDataBinding> {
            val binding = DataBindingUtil.inflate<ViewDataBinding>(LayoutInflater.from(parent.context), layouts.get(viewType), parent, false)
            onCreateViewHolderDecorate(binding, viewType)
            return BindViewHolder(binding.root, binding)
        }
    
        open fun onCreateViewHolderDecorate(view: ViewDataBinding, viewType: Int) {
    
        }
    
        override fun getItemViewType(position: Int): Int {
            return mDatas.get(position).itemType
        }
    
        fun addItemType(type: Int, @LayoutRes layoutResId: Int) {
            layouts.put(type, layoutResId)
        }
    }
    
    class BindViewHolder<VB>(itemView: View, val binding: VB) : RecyclerView.ViewHolder(itemView)
    
    /**
     * 多type的需要用这个包装实体类
     */
    class MultiItem<T>(var itemType: Int, var data: T) {
        override fun toString(): String {
            return "MultiItem(itemType=$itemType, data=$data)"
        }
    }
    
    /**
     * Created by 田桂森 on 2017/8/17.
     * 如果不需要设置item中子类点击事件用这个
     */
    
    class SimpleAdapter<E : Any>(datas: MutableList<E>, layoutId: Int) : BaseSigleAdapter<E, ViewDataBinding>(datas, layoutId) {
        override fun decorator(bean: E, holder: BindViewHolder<ViewDataBinding>, position: Int) {
    
        }
    }
    /**
     * Created by 田桂森 on 2017/8/18.
     * 多type如果不需要设置item中子类子类点击事件用这个
     */
    class SimpleMultiAdapter<E : Any>(datas: MutableList<MultiItem<E>>) : BaseMultiAdapter<E>(datas) {
        override fun decorator(bean: MultiItem<E>, holder: BindViewHolder<ViewDataBinding>, position: Int) {
    
        }
    }
    

    相关文章

      网友评论

        本文标题:使用kotlin和databinding简单封装adapter

        本文链接:https://www.haomeiwen.com/subject/rgmcqqtx.html