ViewModel 在 Activity 中的实现原理

系统源码参考自 Android API 30 Platform,以及 androidx.lifecycle:lifecycle-viewmodel:2.2.0


在文章开始之前,有如下几点疑惑,先记录下来:

  1. ViewModel#onCleared() 的调用时机 ?
  2. ViewModel 与 onSaveInstanceState() 有联系吗?或者有什么区别吗?
  3. ViewModel 是否涉及序列化与反序列化?
  4. 一个 Activity 中是否支持多个 ViewModel ?
  5. ViewModelProvider#get() 的使用时机。

1. 与 ViewModel 相关的类

1.1 ViewModelStoreViewModelStoreOwner

ViewModel 实现的关键就是 ViewModelStore,其内部有一个 HashMap<String, ViewModel> 用于存储多个 ViewModel 实例,即本质上就是一个用来维护多个 ViewModel 实例的 map 容器。

public class ViewModelStore {
   

    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    final void put(String key, ViewModel viewModel) {
   
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
   
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
   
        return mMap.get(key);
    }

    ...
}

另外,还涉及到 ViewModelStoreOwner 接口。

public interface ViewModelStoreOwner {
   
    @NonNull
    ViewModelStore getViewModelStore();
}

1.2 androidx.activity.ComponentActivity

androidx.activity.ComponentActivity(源码基于 androidx.activity:activity:1.1.0),就是我们常用的 androidx.appcompat.app.AppCompatActivity的父类。

androidx.activity.ComponentActivity 继承自 androidx.core.app.ComponentActivity,且实现了 ViewModelStoreOwner 接口,同时内部维护了对应的成员变量 mViewModelStoreViewModelStore 类型的)。
在这里插入图片描述

// androidx.activity.ComponentActivity

@NonNull
@Override
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.");
	}
    if (mViewModelStore == null) {
   
      	// NonConfigurationInstances 为 ComponentActivity 中的内部静态类
        NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
   
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        // 如果前面都没有获取到 ViewModelStore 实例,则这里直接实例化一个新的
        if (mViewModelStore == null) {
   
            mViewModelStore = new ViewModelStore();
        }
    }
    return mViewModelStore;
}

static final class NonConfigurationInstances {
   
    Object custom;
    ViewModelStore viewModelStore;
}

getLastNonConfigurationInstance()android.app.Activity 的成员方法。

// android.app.Activity

/**
 * Retrieve the non-configuration instance data that was previously
 * returned by {@link #onRetainNonConfigurationInstance()}.  This will
 * be available from the initial {@link #onCreate} and
 * {@link #onStart} calls to the new instance, allowing you to extract
 * any useful dynamic state from the previous instance.
 *
 * <p>Note that the data you retrieve here should <em>only</em> be used
 * as an optimization for handling configuration changes.  You should always
 * be able to handle getting a null pointer back, and an activity must
 * still be able to restore itself to its previous state (through the
 * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
 * function returns null.
 *
 * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
 * {@link Fragment#setRetainInstance(boolean)} instead; this is also
 * available on older platforms through the Android support libraries.
 *
 * @return the object previously returned by {@link #onRetainNonConfigurationInstance()}
 */
@Nullable
public Object getLastNonConfigurationInstance() {
   
  	// mLastNonConfigurationInstances 则是在 Activity 中定义的内部静态类 ComponentActivity.NonConfigurationInstances 类型
    return mLastNonConfigurationInstances != null
            ? mLastNonConfigurationInstances.activity : null;
}

static final class NonConfigurationInstances {
   
    Object activity;
    HashMap<String, Object> children;
    FragmentManagerNonConfig fragments;
    ArrayMap<String, LoaderManager> loaders;
    VoiceInteractor voiceInteractor;
}

android.app.Activity 内部维护着成员变量 mLastNonConfigurationInstances,其是在 Activity#attach() 中被赋值的,其中 lastNonConfigura

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值