DataBinding

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

2018-08-20  本文已影响311人  vb12

因为有了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

上一篇下一篇

猜你喜欢

热点阅读