MVVM模式结合RecycleView去使用

MVVM模式的概念

MVVM的意思就是model,view,viewmodel,跟MVC和MVP模式的区别就是数据业务处理逻辑全部放在viewmodel中,然后视图跟实体绑定,一方数据改变的话不用再去手动更新数据了,会自动更新的。

不管是MVVM还是MVC或者MVP,它们终究只是一种架构模式,我们了解了大概的样式后 ,就能去实现了,而不是一定要使用特定的技术,第三方库,不要把自己局限住了。

就像MVVM模式主要的概念是什么?第一个就是视图跟实体的绑定,可以省去我们很多findviewbyid这种代码,谷歌官方就提供了DataBinding这种工具供我们去实现视图跟实体的绑定。第二个就是数据业务处理逻辑,如果都放在activity中,activity就显得很臃肿,所以谷歌官方提供了ViewModel这个类让我们在里面处理数据。

谷歌官方提供了4大组件让我们去实现MVVM模式,分别是Databinding,ViewModel,Livedata,Lifecycle,但这个例子中我们只用Databinding,ViewModel,Livedata这3个,这3个组件单拎一个出来都能写一篇文章了,不了解这3个组件的可以去看看官网的文档或者找其它博客看一下,我们直接进入实战。

第一步

请在应用模块的 build.gradle 文件中启用 dataBinding 构建选项,如以下示例所示:

android {
    ...
    buildFeatures {
        dataBinding true
    }
}

然后还得导入ViewModel,Livedata的依赖

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.1")

第二步

创建你所需的实体类,这是我之前做的demo,有用到了Room,大家可以选择加或不加。

@Entity
data class SearchHistory (
    @PrimaryKey(autoGenerate = true)
    var mId:Int,
    var mSearchText:String
){
    constructor():this(0,"")
}

第三步

把你的布局文件传成databinding格式,因为我们要用到recycleview,所以主布局和item布局都要转换,来到我们的xml布局下,对着xml的第一行,按下Alt + Enter,选择 “Convert to data binding layout”,就可以生成DataBinding的布局规则

image

转换完就是这种格式

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </RelativeLayout>
</layout>

第四步

来到activity里绑定布局文件,框架自动会生成DataBinding类,类名是:xml名称+Binding,databinding调用视图组件啥的,直接对象名.id名就可以了。id名也会变成驼峰形式。顺便把我们等等要用到的viewmodel和适配器都初始化了


class SearchActivity : AppCompatActivity() {

    private lateinit var mBinding: ActivitySearchBinding
    private lateinit var mHistoryViewModel: SearchHistoryViewModel
    private lateinit var mSearchHistoryAdapter: SearchHistoryAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_search)
        mHistoryViewModel = ViewModelProvider(this).get(SearchHistoryViewModel::class.java)
        initRecyclerView()

		//这里通过LivaData动态更新数据
        mHistoryViewModel.getSearchHistoryList().observe(this, Observer {
            mSearchHistoryAdapter.setData(it)//这里的it指的是getSearchHistoryList获得的list集合
        })
        mHistoryViewModel.loadSearchHistorys()
      
    }

    fun initRecyclerView() {
        val searchHistoryListView = mBinding.rvSearchHistory
        searchHistoryListView.layoutManager = GridLayoutManager(this, 4)
        mSearchHistoryAdapter = SearchHistoryAdapter()
        searchHistoryListView.adapter = mSearchHistoryAdapter

    }
}

第五步

准备好ViewModel,我这里是用到了Room数据库存取数据,大家可以根据自己的需求去改。

class SearchHistoryViewModel: ViewModel() {

    private val searchHistoryList: MutableLiveData<List<SearchHistory>> = MutableLiveData<List<SearchHistory>>()

    fun getSearchHistoryList(): MutableLiveData<List<SearchHistory>> {
        return searchHistoryList
    }

    fun addSearchHistory(searchText: String) {
        var searchHistory = SearchHistory()
        searchHistory.mSearchText = searchText
        Thread{
            MyApplication.getInstance().getDatabase().searchHistoryDao().insert(searchHistory)
        }.start()
        loadSearchHistorys()
    }

    fun deleteAllSearchHistorys() {
        Thread{
            MyApplication.getInstance().getDatabase().searchHistoryDao().deleteAll()
        }.start()
        loadSearchHistorys()
    }

    fun loadSearchHistorys() {
        Thread{
            val searchHistorys = MyApplication.getInstance().getDatabase().searchHistoryDao().getAll()
            searchHistoryList.postValue(searchHistorys)
        }.start()
    }
}

第六步

准备好Adapter,可以看到之前我们在viewHolder类里面的时候要绑定一堆数据,不停地去findviewbyid,用了databinding后只需绑定一个对象就够了

class SearchHistoryAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var mSearchHistoryList: List<SearchHistory> = emptyList()

    fun setData(searchHistoryList: List<SearchHistory>){
        mSearchHistoryList = searchHistoryList
        notifyDataSetChanged()
    }

    class viewHolder(private val binding: ItemSearchHistoryBinding): RecyclerView.ViewHolder(binding.root) {

        fun bind(searchHistory: SearchHistory){
            binding.searchHistory = searchHistory
            binding.executePendingBindings()
        }
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val binding = DataBindingUtil.inflate<ItemSearchHistoryBinding>(
            LayoutInflater.from(parent.context)
            , R.layout.item_search_history, parent, false)

        return viewHolder(binding)
    }

    override fun getItemCount(): Int {
        return mSearchHistoryList?.size?: 0
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val viewholder = holder as viewHolder
        val searchHistory = mSearchHistoryList[position]
        viewholder.bind(searchHistory)
    }
}

第七步

在item布局绑定数据,通过@{}去绑定,如果想双向绑定就加个=号,@={}

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="searchHistory"
            type="com.shun.entity.SearchHistory" />
    </data>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="@dimen/padding_super_tiny">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true"
            android:focusable="true"
            android:textColor="@color/common_text_gray"
            android:layout_gravity="center"
            android:text="@{searchHistory.MSearchText}"
            android:textSize="@dimen/text_size_normal"
            android:background="@drawable/selector_history"
            android:id="@+id/tv_search_history"/>


    </LinearLayout>
</layout>

想添加事件处理的话,可以去看我之前写的文章

RecycleView的点击事件处理-CSDN博客

我这个demo删了很多东西,所以是运行不了的,主要给大家看个思路。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值