10-JetPack项目实战-实现App共享ViewModel

前提

看懂本文的前提是,了解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.ViewModelStoreOwner

class App :Application(),ViewModelStoreOwner{

    //ViewModelStore单例,在整个系统中只有一个对象
    private var mAppViewModelStore:ViewModelStore? = null
    private var mFactory:ViewModelProvider.Factory? = null

    override 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,而不是App
            return ViewModelProvider.AndroidViewModelFactory.getInstance(applicaiton)
        }
        return mFactory
    }

    // 监测下 Activity是否为null
    private 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: ViewModelStore
        get() = 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.BarUtils

open class BaseActivity:AppCompatActivity() {
    //声明共享ViewModel对象
    private lateinit var sharedViewModel:SharedViewModel

    override 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)
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值