前提
看懂本文的前提是,了解ViewModel源码,Activity是如何存储ViewModel保证数据稳定性的。
本文使用Kotlin编写。
简介
在App开发过程中,会遇到需要全局共享的数据,例如:用户登录信息。
在使用MVVM框架时,ViewModel+DataBinding+LiveData来实现界面和ViewModel双向绑定的时候。使用ViewModel来存储数据,当ViewModel中的LiveData数据发生改变时,能同时更新界面的数据。
此时就会需要一个全局共享的ViewModel。当用户信息改变的时候,需要通知所有与用户相关的界面。(正在展示的和未展示的)
思路
如何实现一个全局共享的ViewModel呢?
在Applicaiton中直接创建和实例化一个全局共享ViewModel可以,Activity/Fragment中使用Applicaiton来获取ViewModel当然可以。
此文提供一种更好的方式,让共享ViewModel同普通ViewModel一样使用。
模拟普通ViewModel的创建过程,在Applicaiton中创建一个唯一的ViewModelStore来存储共享ViewModel,来保证共享VIewModel的唯一性。
在BaseActivity/BaseFragment中声明并通过Applicaiton获取共享ViewModel,让所有实现了BaseActivity/BaseFragment的Activity/Fragment都拥有一个共享ViewModel变量。
实现
全局App类,提供唯一ViewModelStore,ViewModelStore用于存储共享ViewModel,保证共享ViewModel的唯一性。
要点:
- App要实现ViewModelStoreOwner接口。
- ViewModelStore的实例化要保证唯一(在onCreate中实例化)。
- 创建ViewModelProvider时要注意传入的ViewModelStoreOwner对象,要是App类对象,才能保证获取到的是App类中实例化的ViewModelStore对象。
- ViewModelStoreOwner接口的函数getViewModelStore()的返回对象要是App类中的ViewModelStore对象。
import android.app.Activity
import android.app.Application
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwnerclass App :Application(),ViewModelStoreOwner{//ViewModelStore单例,在整个系统中只有一个对象private var mAppViewModelStore:ViewModelStore? = nullprivate var mFactory:ViewModelProvider.Factory? = nulloverride fun onCreate() {super.onCreate()//ViewModelStor初始化mAppViewModelStore = ViewModelStore()}fun getAppViewModelProvider(activity: Activity):ViewModelProvider{/*** 创建ViewModelProvider对象* 第一个参数是ViewModelStoreOwner类型,用于使用getViewModelStore()获取ViewModelStore,此处需要使用的是* 在App类中声明的mAppViewModelStore变量,为了获取到该变量,让App类实现ViewModelStoreOwner接口以及其getViewModelStore()方法。** 第二个参数是ViewModelProvider.Factory类型,使用getAppFactory()方法返回一个AndroidViewModelFactory对象。* AndroidViewModelFactory对象传入的Activity,让共享ViewModel能获取到Activity对象,可以进行页面跳转。*/return ViewModelProvider(activity.applicationContext as App,getAppFactory(activity)!!)}private fun getAppFactory(activity: Activity):ViewModelProvider.Factory?{val applicaiton = checkApplication(activity)if(mFactory == null) {//注意此处创建AndroidViewModelFactory,传入的是Activity,而不是Appreturn ViewModelProvider.AndroidViewModelFactory.getInstance(applicaiton)}return mFactory}// 监测下 Activity是否为nullprivate fun checkApplication(activity: Activity): Application {return activity.application?: throw IllegalStateException("Your activity/fragment is not yet attached to "+ "Application. You can't request ViewModel before onCreate call.")}//注意要返回mAppViewModelStore,才能保证ViewModelStore的唯一性override val viewModelStore: ViewModelStoreget() = mAppViewModelStore!!}
共享ViewModel类
import androidx.lifecycle.ViewModel/*** SharedViewModel的职责是用于 页面通信的* 共享数据,解决一致性问题*/
class SharedViewModel : ViewModel() {}
基类BaseActivity的实现。
import android.graphics.Color
import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.learn.common.bridge.App
import com.xiangxue.architecture.bridge.callback.SharedViewModel
import com.xiangxue.architecture.utils.BarUtilsopen class BaseActivity:AppCompatActivity() {//声明共享ViewModel对象private lateinit var sharedViewModel:SharedViewModeloverride fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {super.onCreate(savedInstanceState, persistentState)//实例化共享ViewModel对象sharedViewModel = getAppViewModelProvider().get(SharedViewModel::class.java)}//确保ViewModelProvider是单例private fun getAppViewModelProvider():ViewModelProvider{return (applicationContext as App).getAppViewModelProvider(this)}
}