美文网首页DataBinding
利用mvvm框架开发一个通用RecyclerView Adapt

利用mvvm框架开发一个通用RecyclerView Adapt

作者: vb12 | 来源:发表于2018-08-20 20:47 被阅读311次

    因为有了MVVM, 有了其中的ViewModel, 所有的列表控件逻辑都可以放到view层(主要)和viewmodel层(辅助)

    也因此可以把RecyclerView中的ViewHolder角色消减掉. 因为ViewHolder的作用也就是给各个控件赋值, 设置事件处理器, 判断控件是否显示, 等等, 这完全是View层和ViewModel的职责.

    所以就有了本文的这个优化的Adapter.

    interface Data {
        val itemViewType: Int
        val data:Any    // 主ViewModel
        val params:HashMap<Int, Any>     // 附加viewmodel, 当一个布局文件中有多个viewmodel时可以使用
    }
    
    // 这个是最终提交给Adapter的数据元素封装类, 里面包含了具体的数据对象data, 
    // 和布局资源id: itemViewType     
    class FLData(override val data: Any, override val itemViewType: Int,
                 override val params: HashMap<Int, Any> = hashMapOf()) : Data
    
    //  这个就是设置给RecyclerView控件的adapter类
    class MvvmAdapter(
            val context: Context, diffCallback: DiffUtilItemCallback<Data> = DefaultDataDiffCallback()
    ) : ListAdapter<Data, MvvmAdapter.ViewHolder>(diffCallback) {
      
        // 支持多种ItemViewType, 注意这里实际是直接使用布局文件资源id作为ItemViewType
        override fun getItemViewType(position: Int): Int {
            return getItem(position).itemViewType
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            return ViewHolder(
                    DataBindingUtil.inflate(
                            LayoutInflater.from(parent.context),
                            viewType, parent, false
                    )
            )
        }
      
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            var data = getItem(position)
            holder.bind(data)
        }
    
        // 这就是退化后的ViewHolder, 只赋值为xml设置viewmodel对象而已. 
        class ViewHolder(
                private val binding: ViewDataBinding
        ) : RecyclerView.ViewHolder(binding.root) {
    
            fun bind(data: Data) {
                with(binding) {
                    setVariable(BR.viewModel, data.data)
                    data.params?.entries.forEach {
                        (key, value)-> binding!!.setVariable(key, value)
                    }
                    executePendingBindings()
                }
            }
        }
    }
    

    使用时, 在fragment或者activity中

            val binding = DataBindingUtil.inflate<FollowListFragmentBinding>(
                    inflater, R.layout.follow_list_fragment, container, false)
    
            val viewModel = ViewModelProviders.of(this)
                    .get(FollowTopicListViewModel::class.java)
            binding.viewModel = viewModel
    
            val adapter = MvvmAdapter(requireContext())
            binding.followTopicList.adapter =adapter
    

    简单来说, 对于Recyclerview, 再也不考虑在代码层实现一个ViewHolder, 这对于UI元素类别特别多的项目非常有意义, 可以减少大量重复的ViewHolder样式代码.

    具体代码在:
    https://github.com/shaopx/LiteDig

    相关文章

      网友评论

        本文标题:利用mvvm框架开发一个通用RecyclerView Adapt

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