美文网首页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