一、思路
对象是存储在 中的,那么如果我们创建一个全局使用的 并且在获取 对象的时候从它里面获取就可以了。 是通过 的 方法获取的,一般是 - ViewModelProvider(owner: ViewModelStoreOwner, factory: Factory).get(ViewModel::class.java)
复制代码。
如何将 与 关联起来? 纽带就是 , 是一个接口,需要实现 方法,而该方法返回的就是 : - public interface ViewModelStoreOwner {
- /**
- * Returns owned {@link ViewModelStore}
- *
- * @return a {@code ViewModelStore}
- */
- @NonNull
- ViewModelStore getViewModelStore(); //返回一个ViewModelStore
- }
复制代码让某个类实现这个接口,重写方法返回我们定义的 就可以了。
至于上面 构造方法的第二个参数 是什么呢?
源码中提供了二种 ,一种是 ,一种是 ,它们的主要区别是:
- NewInstanceFactory创建ViewModel时,会为每个Activity或Fragment创建一个新的ViewModel实例,这会导致ViewModel无法在应用程序的不同部分共享数据。(ComponentActivity源码getDefaultViewModelProviderFactory方法)
- AndroidViewModelFactory可以访问应用程序的全局状态,并且ViewModel实例可以在整个应用程序中是共享的。
根据我们的需求,需要用的是AndroidViewModelFactory。
二、具体实现
1、方式一:可以全局添加和获取任意
定义Application, 文件 - import android.app.Application
- lateinit var appContext: Application
- fun setApplicationContext(context: Application) {
- appContext = context
- }
复制代码定义全局可用的 实现类 - object ApplicationScopeViewModelProvider : ViewModelStoreOwner {
- private val eventViewModelStore: ViewModelStore = ViewModelStore()
- override fun getViewModelStore(): ViewModelStore {
- return eventViewModelStore
- }
- private val mApplicationProvider: ViewModelProvider by lazy {
- ViewModelProvider(
- ApplicationScopeViewModelProvider,
- ViewModelProvider.AndroidViewModelFactory.getInstance(appContext)
- )
- }
- fun <T : ViewModel> getApplicationScopeViewModel(modelClass: Class<T>): T {
- return mApplicationProvider.get(modelClass)
- }
- }
复制代码定义一个 通过 定义发送和订阅事件的方法 - class EventViewModel : ViewModel() {
- private val mutableStateFlow = MutableStateFlow(0)
- fun postEvent(state: Int) {
- mutableStateFlow.value = state
- }
- fun observeEvent(scope: CoroutineScope? = null, method: (Int) -> Unit = { _ -> }) {
- val eventScope = scope ?: viewModelScope
- eventScope.launch {
- mutableStateFlow.collect {
- method.invoke(it)
- }
- }
- }
- }
复制代码定义一个调用的类 - object FlowEvent {
- //发送事件
- fun postEvent(state: Int) {
- ApplicationScopeViewModelProvider.getApplicationScopeViewModel(EventViewModel::class.java)
- .postEvent(state)
- }
- //订阅事件
- fun observeEvent(scope: CoroutineScope? = null, method: (Int) -> Unit = { _ -> }) {
- ApplicationScopeViewModelProvider.getApplicationScopeViewModel(EventViewModel::class.java)
- .observeEvent(scope, method)
- }
- }
复制代码测试代码如下: - class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- //打印协程名称
- System.setProperty("kotlinx.coroutines.debug", "on")
- FlowEvent.observeEvent {
- printMsg("MainActivity observeEvent before :$it")
- }
- //修改值
- FlowEvent.postEvent(1)
- FlowEvent.observeEvent {
- printMsg("MainActivity observeEvent after :$it")
- }
- }
- }
- //日志
- 内容:MainActivity observeEvent before :0 线程:main @coroutine#1
- 内容:MainActivity observeEvent before :1 线程:main @coroutine#1
- 内容:MainActivity observeEvent after :1 线程:main @coroutine#2
复制代码 2、方式二:更方便在Activity和Fragment中调用
定义Application,让 实现 - //BaseApplication实现ViewModelStoreOwner接口
- class BaseApplication : Application(), ViewModelStoreOwner {
- private lateinit var mAppViewModelStore: ViewModelStore
- private var mFactory: ViewModelProvider.Factory? = null
- override fun onCreate() {
- super.onCreate()
- //设置全局的上下文
- setApplicationContext(this)
- //创建ViewModelStore
- mAppViewModelStore = ViewModelStore()
- }
- override fun getViewModelStore(): ViewModelStore = mAppViewModelStore
- /**
- * 获取一个全局的ViewModel
- */
- fun getAppViewModelProvider(): ViewModelProvider {
- return ViewModelProvider(this, this.getAppFactory())
- }
- private fun getAppFactory(): ViewModelProvider.Factory {
- if (mFactory == null) {
- mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(this)
- }
- return mFactory as ViewModelProvider.Factory
- }
- }
复制代码文件也有变化,如下 - lateinit var appContext: Application
- fun setApplicationContext(context: Application) {
- appContext = context
- }
- //定义扩展方法
- inline fun <reified VM : ViewModel> Fragment.getAppViewModel(): VM {
- (this.requireActivity().application as? BaseApplication).let {
- if (it == null) {
- throw NullPointerException("Application does not inherit from BaseApplication")
- } else {
- return it.getAppViewModelProvider().get(VM::class.java)
- }
- }
- }
- //定义扩展方法
- inline fun <reified VM : ViewModel> AppCompatActivity.getAppViewModel(): VM {
- (this.application as? BaseApplication).let {
- if (it == null) {
- throw NullPointerException("Application does not inherit from BaseApplication")
- } else {
- return it.getAppViewModelProvider().get(VM::class.java)
- }
- }
- }
复制代码在 和 中调用上述扩展方法 - abstract class BaseActivity: AppCompatActivity() {
- //创建ViewModel对象
- val eventViewModel: EventViewModel by lazy { getAppViewModel() }
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- }
- }
复制代码- abstract class BaseFragment: Fragment() {
- //创建ViewModel对象
- val eventViewModel: EventViewModel by lazy { getAppViewModel() }
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- }
- }
复制代码测试代码 - class MainActivity : BaseActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- //打印协程名称
- System.setProperty("kotlinx.coroutines.debug", "on")
- eventViewModel.observeEvent {
- printMsg("MainActivity observeEvent :$it")
- }
- findViewById<AppCompatButton>(R.id.bt).setOnClickListener {
- //点击按钮修改值
- eventViewModel.postEvent(1)
- //跳转到其他Activity
- Intent(this, TwoActivity::class.java).also { startActivity(it) }
- }
- }
- }
复制代码- class TwoActivity : BaseActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_two)
- eventViewModel.observeEvent {
- printMsg("TwoActivity observeEvent :$it")
- }
- }
- }
复制代码日志 - 内容:MainActivity observeEvent :0 线程:main @coroutine#1
- 内容:MainActivity observeEvent :1 线程:main @coroutine#1
- 内容:TwoActivity observeEvent :1 线程:main @coroutine#2
复制代码以上就是详解Android如何设计一个全局可调用的ViewModel对象的详细内容,更多关于Android ViewModel对象的资料请关注晓枫资讯其它相关文章!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |