利用mvvm框架開發(fā)一個(gè)通用RecyclerView Adapter

因?yàn)橛辛薓VVM, 有了其中的ViewModel, 所有的列表控件邏輯都可以放到view層(主要)和viewmodel層(輔助)

也因此可以把RecyclerView中的ViewHolder角色消減掉. 因?yàn)閂iewHolder的作用也就是給各個(gè)控件賦值, 設(shè)置事件處理器, 判斷控件是否顯示, 等等, 這完全是View層和ViewModel的職責(zé).

所以就有了本文的這個(gè)優(yōu)化的Adapter.

interface Data {
    val itemViewType: Int
    val data:Any    // 主ViewModel
    val params:HashMap<Int, Any>     // 附加viewmodel, 當(dāng)一個(gè)布局文件中有多個(gè)viewmodel時(shí)可以使用
}

// 這個(gè)是最終提交給Adapter的數(shù)據(jù)元素封裝類, 里面包含了具體的數(shù)據(jù)對(duì)象data, 
// 和布局資源id: itemViewType     
class FLData(override val data: Any, override val itemViewType: Int,
             override val params: HashMap<Int, Any> = hashMapOf()) : Data

//  這個(gè)就是設(shè)置給RecyclerView控件的adapter類
class MvvmAdapter(
        val context: Context, diffCallback: DiffUtilItemCallback<Data> = DefaultDataDiffCallback()
) : ListAdapter<Data, MvvmAdapter.ViewHolder>(diffCallback) {
  
    // 支持多種ItemViewType, 注意這里實(shí)際是直接使用布局文件資源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設(shè)置viewmodel對(duì)象而已. 
    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()
            }
        }
    }
}

使用時(shí), 在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

簡(jiǎn)單來說, 對(duì)于Recyclerview, 再也不考慮在代碼層實(shí)現(xiàn)一個(gè)ViewHolder, 這對(duì)于UI元素類別特別多的項(xiàng)目非常有意義, 可以減少大量重復(fù)的ViewHolder樣式代碼.

具體代碼在:
https://github.com/shaopx/LiteDig

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,820評(píng)論 25 708
  • 1、概述 Databinding 是一種框架,MVVM是一種模式,兩者的概念是不一樣的。我的理解DataBindi...
    Kelin閱讀 76,861評(píng)論 68 521
  • 在喧囂繁雜的城市中,靜謐安然,純粹靈性,是我對(duì)古木演義的第一印象。 進(jìn)入古木演義,隨之而來的是...
    o小穎姑娘閱讀 276評(píng)論 2 1
  • 1. 又快到年關(guān)了,每到這個(gè)時(shí)節(jié)都會(huì)有不間斷的飯局。畢竟,人是群居動(dòng)物,而且還有很強(qiáng)的社會(huì)屬性,在一起吃飯...
    展夢(mèng)之翼閱讀 729評(píng)論 0 1
  • 曾有人跟我說:“你為什么要留長(zhǎng)指甲呀,你不會(huì)不知道女生一般都不會(huì)喜歡男生留長(zhǎng)指甲吧?” “我知道” “那你……” ...
    歐陽(yáng)離思閱讀 244評(píng)論 5 1