利用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样式代码.