简单通用的 Recyclerview Adapter

作者: flaming | 来源:发表于2018-02-21 14:44 被阅读66次

    方案1

    Android内容展示类的应用中 Recyclerview使用非常频繁,为Recyclerview写Adapter是一件很麻烦的事情。经过不断的改进,诞生了一个令人满意的简单通用的Adapter。通用是指对应任意的数据类型,和任意的布局效果都可以适用。暂不考虑多种数据和布局混排的情况。

    下面是该Adapter的kotlin代码

    open class CommonAdapter<T>(private val mLayoutId: Int, val bind: (CommonViewHolder, Int, T) -> Unit) : RecyclerView.Adapter<CommonViewHolder>() {
    
        private var mContent: MutableList<T> = mutableListOf()
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CommonViewHolder {
            val view = createView(parent, viewType)
            return CommonViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: CommonViewHolder, position: Int) {
            bind(holder, position, mContent[position])
        }
        override fun getItemCount(): Int = mContent.size
        protected fun createView(parent: ViewGroup, viewType: Int): View {
            return LayoutInflater.from(parent.context).inflate(mLayoutId, parent, false)
        }
        fun addItems(items: List<T>?, append: Boolean) {
            items?.let {
                if (!append) {
                    mContent.clear()
                }
                mContent.addAll(it)
                notifyDataSetChanged()
            }
        }
    }
    
    非常关键的通用viewholder
    
    class CommonViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    
        private val views: SparseArray<View> = SparseArray()
        operator fun <T : View> get(id: Int): T {
            var t = views.get(id)
            if (t == null) {
                t = itemView.findViewById(id)
                views.put(id, t)
            }
            return t as T
        }
    }
    
    使用Adapter的demo
    
    fun provideHomeAdapter():CommonAdapter<Girl>{
            return CommonAdapter(R.layout.viewholder_girl, { h, _, d ->
                h.get<TextView>(R.id.des_view).text=d.desc
                Glide.with(activity).load(d.url).fitCenter().into(h.get(R.id.image_view))
            })
        }
    
    
    

    简单解释一下,主要是把变化的内容抽象出来,通过参数传入。借助kotlin的闭包让代码更精简,不必向java那样为每一种操作定义接口。

    方案2

    其实还有更简单的方法,借助Databinding框架实现更加简单的通用的Adapter。数据绑定的代码都可以在布局文件中实现。

    下面是使用Databinding实现的Adapter

    class DataBindingAdapter<T>(val layoutId:Int, val mContent:List<T>) :
            RecyclerView.Adapter<DataBindingViewHolder>() {
        
        override fun onBindViewHolder(holder:DataBindingViewHolder, position: Int) {
            holder.binding?.let {
                it.setVariable(BR.data,mContent[position])//xml文件中变量名称要一致
                it.executePendingBindings() //立刻执行数据绑定
            }
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBindingViewHolder {
            val binding=DataBindingUtil.inflate<ViewDataBinding>(LayoutInflater.from(parent.context), layoutId, parent,false)
            val holder= DataBindingViewHolder(binding.root)
            holder.binding=binding
            return holder
        }
        override fun getItemCount()= mContent.size
    }
    
    viewholder
    
    class DataBindingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
          var binding:ViewDataBinding?=null
    }
    
    xml布局文件略
    
    

    简单的不像话。

    注意事项:要想使用DatabindingAdaper 要遵循一个约定,布局文件的viewmodel名称为data。

    其实方案1和2比也不是一无是处,有些情况下,它更加灵活。至少不需要借助其他框架

    多种数据和布局混排的情况

    这种情况也非常的常见。简单的如给Recyclerview加header和footer。这种情况的Adaper实现我见过一个非常好的方法。可以最大程度的复用代码。感兴趣的可以参考以下文档。

    草梯子坏了,找不到了,以后再补吧

    相关文章

      网友评论

        本文标题:简单通用的 Recyclerview Adapter

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