侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 38 篇文章
  • 累计创建 27 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Android Jetpack | ViewModel

慢行的骑兵
2021-09-13 / 0 评论 / 0 点赞 / 925 阅读 / 5,301 字

一.前言

  • 本篇主线包含三个方面,ViewModel是什么、如何使用、源码分析(包含核心类和复用原理)三个方面;

二.ViewModel是什么

  • ViewModel类是被设计用来以可感知生命周期(只能感知宿主的销毁)的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活即使 activity configuration发生变化,比如横竖屏切换的时候。

  • 优点

    • 数据持久化(配置更改时保存数据,临时性内存存储,仅在应用进程存活期间有效);
    • 异步回调问题,不会造成内存泄漏(ViewModel 的生命周期比 Activity/Fragment 长,且不持有它们的引用);
    • 在Mvvm架构中隔离Model层与View层;
    • 可实现Fragments间共享数据;
  • 官网文档

  • 为了便于理解,结合使用场景做一下相关的总结:

    • 在比较早的时候,Activity因为横竖屏切换等原因被销毁,这种异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态。当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。如果被重建了,那么我们就可以取出之前保存的数据并恢复,如果使用了ViewModel,这些工作ViewModel就可以替我们去做了。
    • 在MVVM架构中,VM层是通过自定义ViewModel来实现的,结合Livedata一起使用,VM层是不需要持有UI层的引用就能做到驱动V层UI的更新,能写出耦合性更高、更易于维护的代码;

三.使用

  • 依赖
androidx.appcompat:appcompat:1.6.1
//新建的AS项目,默认包含依赖,androidx.appcompat:appcompat:1.6.1 ,其默认有lifecycle-viewmodel,对应版本为2.6.1。
//为了让学习更简单化,就不额外添加依赖 & 选择使用Java语言的方式来进行使用和分析
  • 定义MyViewModel类
public class MyViewModel extends ViewModel {
    private MutableLiveData<String> number;

    public MutableLiveData<String> getNumber(){
        if(number == null){
            number = new MutableLiveData<>();
            number.setValue("");
        }
        return number;
    }
    
    public String getUserFromNet(){
        //获取数据
        return number.getValue() + "";
    }
}
  • 在MainActivity中使用
public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    TextView mTextView;
    
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.text);
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
    }

    public void changeData(View view) {
        myViewModel.getNumber().setValue(myViewModel.getNumber().getValue() + 1);
        mTextView.setText(myViewModel.getUserFromNet());
    }
}

四.ViewModel的复用原理

4.1.核心类

  • ViewModelProvider:协调创建和获取 ViewModel;
  • ViewModelStoreOwner:接口,其实现类提供 ViewModelStore
    • ComponentActivity类实现了该接口 & 复写了接口中的getViewModelStore()方法;
    • ComponentActivity类还实现了 HasDefaultViewModelProviderFactory 接口 & 重写了getDefaultViewModelProviderFactory 函数,在4.2中分析Factory的实现类时会使用到;
  • ViewModelStore:存储 ViewModel 实例的容器,本质是一个HashMap;
  • Factory:接口,解耦 ViewModel 的创建逻辑,有三个实现类,NewInstanceFactory、AndroidViewModelFactory和SavedStateViewModelFactory;
  • SavedStateHandle:一个ViewModel对应一个SavedStateHandle,用于存储和恢复;

4.2.如何获取ViewModel的实例

  • 将new ViewModelProvider(this).get(MyViewModel.class)拆分为两部分进行分析,查看ViewModelProvider和get,先分析前者:
public constructor(
        owner: ViewModelStoreOwner
    ) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))

//调用另外一个构造函数
constructor(
    private val store: ViewModelStore,
    private val factory: Factory,
    private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
)
  • 由于MainActivity间接继承自ComponentActivity,ComponentActivity实现了ViewModelStoreOwner接口,则可以直接传入this作为参数。
  • 将store(activity)赋值给ComponentActivity类中mViewModelStore(owner.viewModelStore对应的是ComponentActivity类中的getViewModelStore()函数,返回值是ComponentActivity类中的mViewModelStore变量)
  • 分析ViewModelStore类,本质是一个Hashmap
open class ViewModelStore {

    private val map = mutableMapOf<String, ViewModel>()

    /**
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    fun put(key: String, viewModel: ViewModel) {
        val oldViewModel = map.put(key, viewModel)
        oldViewModel?.onCleared()
    }

    /**
     * Returns the `ViewModel` mapped to the given `key` or null if none exists.
     */
    /**
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    operator fun get(key: String): ViewModel? {
        return map[key]
    }

    /**
     * @hide
     */
    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    fun keys(): Set<String> {
        return HashSet(map.keys)
    }

    /**
     * Clears internal storage and notifies `ViewModel`s that they are no longer used.
     */
    fun clear() {
        for (vm in map.values) {
            vm.clear()
        }
        map.clear()
    }
}
  • 接着分析get函数
    • 分析1:获取类的完全限定名,格式为:包名.类名(例如 com.example.MyViewModel);
    • 分析2:将DEFAULT_KEY拼接canonicalName作为get函数的参数1;
    • 分析3:根据key获取ViewModel;
    • 分析4:检查缓存实例是否是 modelClass 类型,符合则返回store[key];
    • 分析5:如果没有找到合适的实例,准备创建新的ViewModel;
    • 分析6:优先使用factory带extras参数的create方法;
    • 分析7:回退到factory不带extras参数的create方法;
    • 分析8:将新创建的ViewModel存入store;
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
	//分析1
    val canonicalName = modelClass.canonicalName
        ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
    //分析2
    return get("$DEFAULT_KEY:$canonicalName", modelClass)
}

@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
    val viewModel = store[key]//分析3
    if (modelClass.isInstance(viewModel)) {//分析4
        (factory as? OnRequeryFactory)?.onRequery(viewModel!!)
        return viewModel as T
    } else {
        @Suppress("ControlFlowWithEmptyBody")
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    val extras = MutableCreationExtras(defaultCreationExtras)//分析5
    extras[VIEW_MODEL_KEY] = key
    // AGP has some desugaring issues associated with compileOnly dependencies so we need to
    // fall back to the other create method to keep from crashing.
    return try {
        factory.create(modelClass, extras)//分析6
    } catch (e: AbstractMethodError) {
        factory.create(modelClass)//分析7
    }.also { store.put(key, it) }//分析8
}
  • 因为factory是接口,我们需要找到具体实现类,回到ViewModelProvider构造函数中发现,factory的赋值时机是调用了defaultFactory函数
    • 分析9:条件成立
    • owner.defaultViewModelProviderFactory对应为ComponentActivity中的getDefaultViewModelProviderFactory函数
public companion object {
    internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =
        if (owner is HasDefaultViewModelProviderFactory)//分析9
            owner.defaultViewModelProviderFactory else instance
    //...
}
  • ComponentActivity中的getDefaultViewModelProviderFactory函数,即:
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    if (mDefaultFactory == null) {
        mDefaultFactory = new SavedStateViewModelFactory(
                getApplication(),
                this,
                getIntent() != null ? getIntent().getExtras() : null);
    }
    return mDefaultFactory;
}
  • 此时,我们看一下Factory的源码,Factory带extras参数的create函数最终还是重载不带extras参数的create(modelClass) 方法
public interface Factory {
    public fun <T : ViewModel> create(modelClass: Class<T>): T {
        throw UnsupportedOperationException(
            "Factory.create(String) is unsupported.  This Factory requires " +
                "`CreationExtras` to be passed into `create` method."
        )
    }

    //...
    public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
        create(modelClass)

    //...
}
  • 回到上方的get函数,不论是执行分析6还是分析7,根据前面的推理,我们可以知晓,代码最终要执行的是SavedStateViewModelFactory类的create(modelClass: Class) 函数,继续查看会执行create(key: String, modelClass: Class)函数,源码如下:
  fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
    // empty constructor was called.
  //检查lifecycle是否存在
    val lifecycle = lifecycle
        ?: throw UnsupportedOperationException(
            "SavedStateViewModelFactory constructed with empty constructor supports only " +
                "calls to create(modelClass: Class<T>, extras: CreationExtras)."
        )
    //分析10
    val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
  //分析11  
  val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
  		//分析12
        findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
    } else {
  		//分析13
        findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
    }
   //分析14
    // doesn't need SavedStateHandle
    constructor
        ?: // If you are using a stateful constructor and no application is available, we
        // use an instance factory instead.
        return if (application != null) factory.create(modelClass)//分析15
        else instance.create(modelClass)//分析16
  //分析17
    val controller = LegacySavedStateHandleController.create(
        savedStateRegistry!!, lifecycle, key, defaultArgs
    )
  //分析18
    val viewModel: T = if (isAndroidViewModel && application != null) {
        newInstance(modelClass, constructor, application!!, controller.handle)
    } else {
        newInstance(modelClass, constructor, controller.handle)
    }
  //分析19
    viewModel.setTagIfAbsent(
        AbstractSavedStateViewModelFactory.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller
    )
  //分析20
    return viewModel
}
  • 分析10:判断要创建的ViewModel是否是AndroidViewModel的子类
  • 分析11:根据ViewModel类型查找匹配的构造函数,查看一下findMatchingConstructor函数(上方代码中,由于 MyViewModel 只有无参构造器,findMatchingConstructor 会返回 null)
private val ANDROID_VIEWMODEL_SIGNATURE = listOf<Class<*>>(
    Application::class.java,
    SavedStateHandle::class.java
)
private val VIEWMODEL_SIGNATURE = listOf<Class<*>>(SavedStateHandle::class.java)
//内部函数,泛型T表示目标类型,查找modelClass中与signature参数列表匹配的构造函数
internal fun <T> findMatchingConstructor(
    modelClass: Class<T>,// 要查找的类对象
    signature: List<Class<*>>// 期望的参数类型列表
): Constructor<T>? {// 返回找到的构造器或null
  // 11.1. 遍历目标类的所有构造函数
    for (constructor in modelClass.constructors) {
  // 11.2. 获取当前构造函数的参数类型列表
        val parameterTypes = constructor.parameterTypes.toList()
  // 11.3. 检查参数类型是否完全匹配signature
        if (signature == parameterTypes) {
  // 11.4. 类型匹配时,抑制类型转换警告并返回构造器
            @Suppress("UNCHECKED_CAST")
            return constructor as Constructor<T>
        }
  // 11.5. 检查参数数量相同但顺序不对的情况
        if (signature.size == parameterTypes.size && parameterTypes.containsAll(signature)) {
  // 11.6. 抛出异常提示参数顺序错误          
  throw UnsupportedOperationException(
                "Class ${modelClass.simpleName} must have parameters in the proper " +
                    "order: $signature"
            )
        }
    }
  // 11.7. 没有找到匹配的构造函数则返回null
    return null
}
  • 分析12:如果是AndroidViewModel且有Application上下文,查找带Application和SavedStateHandle参数的构造器

  • 分析13:普通ViewModel,查找带SavedStateHandle参数的构造器

  • 分析14,因为分析11位置得到的结果constructor是为null,所以这里要么执行分析15,要么执行分析16。两者执行其中一个之后,方法就return,后面代码就不执行了。附上一张流程图
    deepseek_mermaid_20250819_759c2f

    • 分析15:factory = ViewModelProvider.AndroidViewModelFactory(),即:执行AndroidViewModelFactory的create函数;
    • 分析16:sInstance = NewInstanceFactory(),即:执行NewInstanceFactory的create函数;
  • 分析17:创建SavedStateHandleController

  • 分析18:根据构造器参数创建viewModel(将 SavedStateHandle 注入到 ViewModel 中)

  • 分析19:为viewModel加上标签

  • 分析20:返回viewModel

  • 总结:ViewModelProvider,本质是从传递进去的ViewModelStoreOwner来获取实例,如果没有,则利用Factory来创建。而Factory有三个实现类,其区别如下:

    • NewInstanceFactory:直接反射构建出viewModel;
    • AndroidViewModelFactory:构建时需要传递一个Application;
    • SavedStateViewModelFactory:构建时会传递一个SavedStateHandle对象,可以取代onSaveInstanceState 和 onRestoreInstanceState用来存储和恢复数据。这种存储方式,即使页面因配置变更、内存不足被系统回收,重建时都可以恢复数据;
  • Factory的create(modelClass) 方法执行具体是指向哪个实现类由我们所写的代码方式来决定,我们分别举例一个场景来说明:

    • 未指定 Factory & ViewModel 必须有无参构造函数,则使用的 Factory的create(modelClass) 方法对应为NewInstanceFactory;
    //V层中调用
    myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
    //MyViewModel类,ViewModel 必须有无参构造函数
    public class MyViewModel extends ViewModel {
        private MutableLiveData<String> number;
    
        public MutableLiveData<String> getNumber(){
            if(number == null){
                number = new MutableLiveData<>();
                number.setValue("");
            }
            return number;
        }
    
        public String getUserFromNet(){
            //获取数据
            return number.getValue() + "";
        }
    }  
    
    • ViewModel继承 AndroidViewModel & 显式指定 AndroidViewModelFactory,则使用的 Factory的create(modelClass) 方法对应为AndroidViewModelFactory;
      // V层显式使用 AndroidViewModelFactory
    val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application)
    val viewModel = ViewModelProvider(this, factory).get(MyAndroidViewModel::class.java)
      //ViewModel自定义类中需要继承 AndroidViewModel
      class MyAndroidViewModel(application: Application) : AndroidViewModel(application)
    
    • ViewModel 需要接收 SavedStateHandle 参数,则使用的 Factory的create(modelClass) 方法对应为SavedStateViewModelFactory;
    // V层使用,默认使用 SavedStateViewModelFactory(自动注入 SavedStateHandle)
    val viewModel = ViewModelProvider(this).get(MyStateViewModel::class.java)
    
    // ViewModel实现类自定义构造
    class MyStateViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
        //...
     	//savedStateHandle["指定的key"]//获取对应key的数据
    	//savedStateHandle["指定的key"] = “目标的数据”//保存指定key的数据
    }  
    

4.3.ViewModel实例的复用原理

  • 我们直接分析使用SavedStateHandle的情况下复用原理,若这种情况弄明白的话,不使用SavedStateHandle的情况下的复用则自然就清楚了。
  • 前置知识,在分析源码之前,需要知道2点:配置变更(如旋转屏幕)或因为内存不足导致进程被杀后重建触发ActivityThread的handleRelaunchActivity,且随后会调用performLaunchActivity函数(大体流程:handleRelaunchActivity->handleRelaunchActivityInner->handleLaunchActivity->performLaunchActivity)& 带SavedStateHandle的ViewModel的简单使用;
  • 源码分析的大体结构如下:MainActivity的onCreate->Factory(对应SavedStateViewModelFactory实现类)的create函数(不带extras参数)->…->配置变更(如旋转屏幕)或因为内存不足导致进程被杀后重建触发->ActivityThread的handleRelaunchActivity->performPauseActivity(内部调用了对应Activity的OnSaveInstanceState函数) & handleDestroyActivity(处理NonConfigurationInstances类相关的)->performLaunchActivity->Activity类中 attach函数 & 对应Activity的onCreate函数->val viewModel = ViewModelProvider(this).get(MyStateViewModel::class.java);

4.3.1.首次执行onCreate函数

  • 根据4.3之前的内容可以知道,我们直接分析SavedStateViewModelFactory类的create(key: String, modelClass: Class)函数中的LegacySavedStateHandleController.create函数,因为使用的是带SavedStateHandle,一定会执行到这里。
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
    //...
    val controller = LegacySavedStateHandleController.create(
        savedStateRegistry!!, lifecycle, key, defaultArgs
    )
    //...
}
  • LegacySavedStateHandleController的create函数,我们重点关注controller.attachToLifecycle(registry, lifecycle),其它的代码一会儿回头进行分析更合适
fun create(
    registry: SavedStateRegistry,
    lifecycle: Lifecycle,
    key: String?,
    defaultArgs: Bundle?
): SavedStateHandleController {
    val restoredState = registry.consumeRestoredStateForKey(key!!)
    val handle = createHandle(restoredState, defaultArgs)
    val controller = SavedStateHandleController(key, handle)
    controller.attachToLifecycle(registry, lifecycle)
    tryToAddRecreator(registry, lifecycle)
    return controller
}
  • controller.attachToLifecycle(registry, lifecycle)函数,我们重点关注registry.registerSavedStateProvider(key, handle.savedStateProvider())
internal class SavedStateHandleController(
    private val key: String,
    val handle: SavedStateHandle
) : LifecycleEventObserver {

    var isAttached = false
        private set

    fun attachToLifecycle(registry: SavedStateRegistry, lifecycle: Lifecycle) {
        check(!isAttached) { "Already attached to lifecycleOwner" }
        isAttached = true
        lifecycle.addObserver(this)
        registry.registerSavedStateProvider(key, handle.savedStateProvider())//分析21
    }

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        if (event === Lifecycle.Event.ON_DESTROY) {
            isAttached = false
            source.lifecycle.removeObserver(this)
        }
    }
}  
  • 分析21:SavedStateRegistry类中的registerSavedStateProvider函数
fun registerSavedStateProvider(
    key: String,
    provider: SavedStateProvider
) {
    val previous = components.putIfAbsent(key, provider)//分析22
    require(previous == null) {
        ("SavedStateProvider with the given key is" +
            " already registered")
    }
}  
  • 分析22:components为SavedStateRegistry类中的成员变量,此时该变量有值了,在分析OnSaveInstanceState函数时会关联到变量;
private val components = SafeIterableMap<String, SavedStateProvider>()  

4.3.2. ComponentActivity类的onSaveInstanceState函数

  • 从ActivityThread的handleRelaunchActivity开始->handleRelaunchActivityInner->performPauseActivity->callActivityOnSaveInstanceState->对应MainActivity的onSaveInstanceState函数,我们分析其间接实现的ComponentActivity类的onSaveInstanceState函数。ActivityThread相关的源码就不展示了,我们仅展示我们要重点分析的源码。
protected void onSaveInstanceState(@NonNull Bundle outState) {
    //...
    mSavedStateRegistryController.performSave(outState);//分析23
} 
  • 分析23:mSavedStateRegistryController.performSave(outState)—>savedStateRegistry.performSave(outBundle)
fun performSave(outBundle: Bundle) {
    val components = Bundle()
    if (restoredState != null) {
        components.putAll(restoredState)
    }
    val it: Iterator<Map.Entry<String, SavedStateProvider>> =
        this.components.iteratorWithAdditions()//分析24
    while (it.hasNext()) {
        val (key, value) = it.next()
        components.putBundle(key, value.saveState())
    }
    if (!components.isEmpty) {
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components)
    }
}  
  • 分析24中有一个this.components,其就是我们在分析22位置的components,其是有值的。那么savedStateRegistry.performSave函数执行之后,outBundle.putBundle(SAVED_COMPONENTS_KEY, components)会调用成功。这里的保存操作是让Bundle来干活的

4.3.3.配置变更对包装类NonConfigurationInstances的处理

  • 从ActivityThread的handleRelaunchActivity开始->handleRelaunchActivityInner->handleDestroyActivity->performDestroyActivity->重点代码:“r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances()”,同理,ActivityThread相关的源码就不展示了,我们仅展示我们要重点分析的源码。
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            boolean getNonConfigInstance, String reason) {
	//...
	r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();//分析25
	//...
}			
  • 分析25:需要拆分成两部分,r.activity.retainNonConfigurationInstances()和对r.lastNonConfigurationInstances的赋值
//Activity的retainNonConfigurationInstances()函数
NonConfigurationInstances retainNonConfigurationInstances() {
    Object activity = onRetainNonConfigurationInstance();//分析26,对应实现为ComponentActivity类的 onRetainNonConfigurationInstance()
    //...

    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.activity = activity;
    //...
    return nci;
}
  • 分析26:ComponentActivity类的 onRetainNonConfigurationInstance(),该函数可能会返回null或者返回一个包装类NonConfigurationInstances,该包装类跟ComponentActivity类中的成员变量关联mViewModelStore。而该成员变量对应一个函数getViewModelStore()来进行获取。
public final Object onRetainNonConfigurationInstance() {
    // Maintain backward compatibility.
    Object custom = onRetainCustomNonConfigurationInstance();

    ViewModelStore viewModelStore = mViewModelStore;// 获取当前Activity的ViewModelStore
    if (viewModelStore == null) {
        // No one called getViewModelStore(), so see if there was an existing
        // ViewModelStore from our last NonConfigurationInstance
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            viewModelStore = nc.viewModelStore;
        }
    }

    if (viewModelStore == null && custom == null) {
        return null;
    }

    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.custom = custom;
    nci.viewModelStore = viewModelStore;//把ViewModelStore放进去
    return nci;
}  
  • 结合分析25和26可以知晓,ComponentActivity类的 onRetainNonConfigurationInstance()返回的结果赋值给了ActivityClientRecord的lastNonConfigurationInstances;

4.3.4.分析ActivityThread中的performLaunchActivity(重建工作)

  • 这里分两个小点,一个是activity.attach函数的分析,另一个是mInstrumentation.callActivityOnCreate(最终是会调用ComponentActivity类的OnCreate函数)函数的分析
    • activity.attach函数:ActivityClientRecord的lastNonConfigurationInstances是该函数的参数,赋值给了Activity类中的mLastNonConfigurationInstances(类型为:NonConfigurationInstances);
    final void attach(//...
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
    	//...
    }  
    
    • ComponentActivity类onCreate函数
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        //...
        mSavedStateRegistryController.performRestore(savedInstanceState);//分析27
        //...
    }  
    
    • 分析27:mSavedStateRegistryController.performRestore(savedInstanceState)—>savedStateRegistry.performRestore(savedState)
    internal fun performRestore(savedState: Bundle?) {
        //...
    	//restoredState是SavedStateRegistry类的成员变量
        restoredState = savedState?.getBundle(SAVED_COMPONENTS_KEY)//分析28
        //...
    }
    
    • 分析28:这里的key为SAVED_COMPONENTS_KEY,跟outBundle.putBundle(SAVED_COMPONENTS_KEY, components)的key相同 & 保存过值的,故restoredState也是有值的。
    • 当ComponentActivity类onCreate函数执行完,会继续执行其实现类MainActivity的onCreate
    public class MainActivity extends AppCompatActivity {
        //...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //...
            myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        }
        //...
    }  
    
    • ViewModel数据的保存和获取已经分析完成。我们再次分析create(key: String, modelClass: Class)函数,重点是分析SavedStateHandle的复用

4.3.4.再次分析SavedStateViewModelFactory的create(key: String, modelClass: Class)函数

fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
    //...
    //分析29
    val controller = LegacySavedStateHandleController.create(
        savedStateRegistry!!, lifecycle, key, defaultArgs
    )
    //分析30
    val viewModel: T = if (isAndroidViewModel && application != null) {
        newInstance(modelClass, constructor, application!!, controller.handle)
    } else {
        newInstance(modelClass, constructor, controller.handle)
    }
    viewModel.setTagIfAbsent(
        AbstractSavedStateViewModelFactory.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller
    )
    return viewModel
}
  • 分析29,内部做了三件事
fun create(
    registry: SavedStateRegistry,
    lifecycle: Lifecycle,
    key: String?,
    defaultArgs: Bundle?
): SavedStateHandleController {
    //事件1:SavedStateRegistry中获取 之前保存起来的Bundle数据
    val restoredState = registry.consumeRestoredStateForKey(key!!)
    //事件2:(使用事件1中获取的数据来)创建SavedStateHandle对象
    val handle = createHandle(restoredState, defaultArgs)
    val controller = SavedStateHandleController(key, handle)
    //事件3:调用SavedStateRegistry的registerSavedStateProvider函数   向数据的存储中心注册一个savedStateProvider
    controller.attachToLifecycle(registry, lifecycle)
    tryToAddRecreator(registry, lifecycle)
    return controller
}
  • 事件1位置的相关源码,在分析28中我们知晓,下方restoredState是有值的,故事件1位置得到的restoredState也是有值的。
@MainThread
fun consumeRestoredStateForKey(key: String): Bundle? {
    //...
    if (restoredState != null) {
        val result = restoredState?.getBundle(key)
        restoredState?.remove(key)
        if (restoredState?.isEmpty != false) {
            restoredState = null
        }
        return result
    }
    return null
}
  • 事件2位置源码分析
fun createHandle(restoredState: Bundle?, defaultState: Bundle?): SavedStateHandle {
    if (restoredState == null) {
        return if (defaultState == null) {
            // No restored state and no default state -> empty SavedStateHandle
            SavedStateHandle()
        } else {
            val state: MutableMap<String, Any?> = HashMap()
            for (key in defaultState.keySet()) {
                state[key] = defaultState[key]
            }
            SavedStateHandle(state)
        }
    }

    //...
    val keys: ArrayList<*>? = restoredState.getParcelableArrayList<Parcelable>(KEYS)
    val values: ArrayList<*>? = restoredState.getParcelableArrayList<Parcelable>(VALUES)
    //...
    val state = mutableMapOf<String, Any?>()
    for (i in keys.indices) {
        state[keys[i] as String] = values[i]
    }
    return SavedStateHandle(state)//分析31
}  
  • 分析31:创建SavedStateHandle时,将传递进来的Bundle类型的restoredState中的数据赋值给Map,然后将该Map通过SavedStateHandle的构造进行传入。即:创建的SavedStateHandle拥有了之前存储到Bundle中的数据了。
  • 分析30:无论是newInstance(modelClass, constructor, application!!, controller.handle)还是执行newInstance(modelClass, constructor, controller.handle),将恢复的Handle(controller.handle)注入到对应的ViewModel实现类的构造函数中,其saveState就有值了,SavedStateHandle的复用也就走通了。数据通过系统机制保存到Bundle,重建时又从Bundle中取出并用于初始化一个新的SavedStateHandle,最后注入到新的ViewModel中。ViewModel实例是新的,但数据是旧的

4.3.5.ViewModelStore的复用

  • 主要依赖于ComponentActivity类中onRetainNonConfigurationInstance() 和 getViewModelStore() 这两个方法的配合
    • onRetainNonConfigurationInstance对应ViewModelStore的保存,在因配置变更而销毁Activity之前,系统会调用此方法。最终是会保存到ActivityClientRecord的lastNonConfigurationInstances中,前面已经分析过;
  • 查看ComponentActivity类的getViewModelStore函数,对应为ViewModelStore的获取;
public ViewModelStore getViewModelStore() {
    if (getApplication() == null) {
        throw new IllegalStateException("Your activity is not yet attached to the "
                + "Application instance. You can't request ViewModel before onCreate call.");
    }
    ensureViewModelStore();
    return mViewModelStore;
}

@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
    if (mViewModelStore == null) {
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;//复用了旧的ViewModelStore
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
}
  • 当mViewModelStore为空的时候,会尝试从 getLastNonConfigurationInstance函数中进行获取,而Activity类中的mLastNonConfigurationInstances赋值时机在4.3.4中提及的attach函数中进行赋值的,为ActivityClientRecord的lastNonConfigurationInstances。而ActivityClientRecord的lastNonConfigurationInstances正好是onRetainNonConfigurationInstance返回的结果,即:取出的ViewModelStore为保存的ViewModelStore,两者是同一个。
public Object getLastNonConfigurationInstance() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }  
  • 不论是否使用SavedStateHandle都会缓存到 ViewModelStore(本质是一个HashMap)中,当因为内存不足等原因发生的重建ViewModel和ViewModelStore都会被销毁的;

五.总结

  • 本文重点对ViewModel的复用原理的详细细节展开了分析,分两种情况,带SavedStateHandle的情况下与不带SavedStateHandle的情况。其中,前者即使应用因内存不足导致进程被杀掉后重建,虽然重建前后的ViewModel不是同一个,但ViewModel依旧可以复用,其底层依赖于Bundle,而因配置文件改变的重建,复用的是同一个ViewModel;而后者在应用进程被杀掉的情况下是不能实现复用的,因配置改变重建是可以实现复用的,重建前后复用的是同一个ViewModel;
0

评论区