使用kotlin和databinding簡單封裝adapter
實現非常簡單,主要運用了databinding的特性實現,使用非常簡單
Adapter" target="_blank" rel="nofollow,noindex">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) { } }