浅析Android Jetpack ACC之ViewModel

一、Android Jetpack简介

Android官网对Jetpack的介绍如下:

Jetpack is a suite of libraries to help developers follow best practices, reduce boilerplate code, and write code that works consistently across Android versions and devices so that developers can focus on the code they care about.

可见Jetpack是一个由多个库组成的套件,使用这个套件可以帮助开发者:

  • 遵循最佳实践:Jetpack提供的组件基于最新的设计方法构建,可以减少崩溃和内存泄漏等问题的出现;
  • 减少样板代码:Jetpack提供的组件提供对繁琐的生命周期、后台任务的管理,帮助开发者实现可维护的代码;
  • 减少差异:实现在不同版本和设备上表现一致的应用,开发者可以集中精力编写对他们来说真正重要的代码,而不是各种版本兼容的代码。

Android官网上对Jetpack组成部分的分类如下图所示(最新官网无下图):
在这里插入图片描述
Android提供的Jetpack一共分为四个部分:架构、基础、UI和行为,其中Android Architecture Component是各个应用使用最多的部分,通常在工程中使用LifecycleLiveData以及ViewModel来实现MVVM架构,因此下面会这三个组件进行分析,《浅析Android Jetpack ACC之Lifecycle》、《浅析Android Jetpack ACC之LiveData》分别对LifecycleLiveData这两个核心组件进行了分析,本文将对ViewModel这个视图模型组件进行分析。

二、ViewModel-自动保存/恢复的视图模型

1. 作用目的

ViewModel组件管理的数据在发生屏幕旋转等配置更改后保留并恢复给后续使用,同时ViewModel组件无需持有View层的引用,因为ViewModel组件主要是为View提供数据但不负责View的更新,ViewModel所扮演的角色与MVP架构中的Presenter层相似,但是不会持有View,数据同步到View层是借助之前分析过的LiveData组件,因此简化了View层与逻辑层之间的依赖关系。

ViewModel组件支持在发生屏幕旋转等配置更改后保留并恢复,因此ViewModel的生命周期一般会比Activity的生命周期要长,两者的生命周期对比如下图所示。
在这里插入图片描述
总结来说,ViewModel组件是一个支持自动保存/恢复的视图模型类,通常结合LiveData组件实现无需持有View层,即可完成数据同步到View层的目的。此外,ViewModel组件支持在同一个Activity下的多个Fragment之间共享数据,这样就可以实现Fragment之间的相互通信。

2. 使用示例

ViewModel组件一般会搭配LiveData组件一起使用,分为以下步骤:

  1. 继承ViewModel类定义自己的ViewModel类(如LocationViewModel类)
  2. Activity/Fragment通过ViewModelProvider获取自定义的ViewModel实例(如LocationViewModel
  3. 通过观察自定义的ViewModel(如LocationViewModel)中的LiveData实现UI更新逻辑
// 1. 自定义ViewModel
class LocationViewModel : ViewModel() {
    private val locationData = MutableLiveData<LocationImpl.Location>()

    fun locationData(): LiveData<LocationImpl.Location> {
        return locationData
    }

    fun startLocation() {
        LocationImpl.startLocation(object : LocationImpl.LocationListener {
            override fun onLocationChanged(location: LocationImpl.Location) {
                locationData.postValue(location)
            }
        })
    }

    fun stopLocation() {
        // stop locate on worker thread
        LocationImpl.stopLocation()
    }
}

class MVVMLocationActivity : ComponentActivity(), IView {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_location)
        // 2. 使用ViewModelProvider获取LocationViewModel实例
        val locationViewModel = ViewModelProvider(this).get(LocationViewModel::class.java)
        // 3. 观察LiveData并在数据变化时刷新UI
        locationViewModel.locationData().observe(this) { location ->
            updateLocation(location)
        }
    }


    override fun updateLocation(location: LocationImpl.Location) {
        // update location
    }
}

通过示例代码可以发现,使用ViewModel以及LiveData组件之后,View层与业务层(MVC中的Controller层、MVP中的Presenter层)之间的依赖关系简化了,ViewModel没有持有View的引用,代码可维护性大大提高。

2. 实现原理

介绍完使用方式之后,但是对于ViewModel如何在发生屏幕旋转等配置更改后依然可以保留并用于后续新的Activity实例,以及如何在多个Fragment之间共享同一个ViewModel,依然还是不清楚,下面就从源码层面分析下这是如何实现的。

目前关于ViewModel只有提到获取方式,那么先从ViewModel实例的获取开始分析:

2.1 ViewModel实例的获取

获取ViewModel实例之前需要构造ViewModelProvider实例,然后调用ViewModelProvider#get方法才能获取ViewModel实例,先看下ViewModelProvider的构造函数,然后再看下ViewModelProvider#get方法的实现。

public actual open class ViewModelProvider private constructor(
    private val impl: ViewModelProviderImpl, // 真正的Provider
) {

    public constructor(
        owner: ViewModelStoreOwner,
    ) : this(
        store = owner.viewModelStore, // 
        factory = ViewModelProviders.getDefaultFactory(owner),
        defaultCreationExtras = ViewModelProviders.getDefaultCreationExtras(owner)
    )

    @JvmOverloads
    public constructor(
        store: ViewModelStore,
        factory: Factory,
        defaultCreationExtras: CreationExtras = CreationExtras.Empty,
    ) : this(ViewModelProviderImpl(store, factory, defaultCreationExtras))

}

internal object ViewModelProviders {
    internal fun getDefaultFactory(owner: ViewModelStoreOwner): ViewModelProvider.Factory =
        if (owner is HasDefaultViewModelProviderFactory) {
            owner.defaultViewModelProviderFactory
        } else {
            DefaultViewModelProviderFactory
        }
}


public interface ViewModelStoreOwner {

    /**
     * The owned [ViewModelStore]
     */
    public val viewModelStore: ViewModelStore
}

在创建ViewModelProvider对象时将ComponentActivity对象传入了构造函数时,而ComponentActivity类实现了ViewModelStoreOwner接口,ViewModelStoreOwner接口内部只定义了一个抽象属性,因此看下ComponentActivity类是如何重写这个抽象属性的访问方法的。

open class ComponentActivity() :
    androidx.core.app.ComponentActivity(),
    ContextAware,
    LifecycleOwner,
    ViewModelStoreOwner,
    HasDefaultViewModelProviderFactory,
    SavedStateRegistryOwner,
    OnBackPressedDispatcherOwner,
    ActivityResultRegistryOwner,
    ActivityResultCaller,
    OnConfigurationChangedProvider,
    OnTrimMemoryProvider,
    OnNewIntentProvider,
    OnMultiWindowModeChangedProvider,
    OnPictureInPictureModeChangedProvider,
    OnUserLeaveHintProvider,
    MenuHost,
    FullyDrawnReporterOwner {

    override val defaultViewModelProviderFactory: ViewModelProvider.Factory by lazy {
        SavedStateViewModelFactory(application, this, if (intent != null) intent.extras else null)
    }

    internal class NonConfigurationInstances {
        var custom: Any? = null
        var viewModelStore: ViewModelStore? = null
    }
    
    override val viewModelStore: ViewModelStore
        /**
         * Returns the [ViewModelStore] associated with this activity
         *
         * Overriding this method is no longer supported and this method will be made `final` in a
         * future version of ComponentActivity.
         *
         * @return a [ViewModelStore]
         * @throws IllegalStateException if called before the Activity is attached to the
         *   Application instance i.e., before onCreate()
         */
        get() {
            checkNotNull(application) {
                ("Your activity is not yet attached to the " +
                    "Application instance. You can't request ViewModel before onCreate call.")
            }
            ensureViewModelStore()
            return _viewModelStore!!
        }

    private fun ensureViewModelStore() {
        if (_viewModelStore == null) {
            val nc = lastNonConfigurationInstance as NonConfigurationInstances?
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                _viewModelStore = nc.viewModelStore
            }
            if (_viewModelStore == null) {
                _viewModelStore = ViewModelStore()
            }
        }
    }
}

可以看到获取viewModelStore属性的值会间接调用ComponentActivity#ensureViewModelStore方法为ComponentActivity的成员变量_viewModelStore进行初始化,注意这里出现了NonConfigurationInstances实例(NonConfigurationInstancesComponentActivity类的一个内部类),如果存在NonConfigurationInstances将会先尝试从这个实例中获取ViewModelStore对象,获取不到或者不存在NonConfigurationInstances实例将会直接构造一个ViewModelStore对象。因此可以猜想ViewModelStore对象可能是借助NonConfigurationInstances实例进行保存和恢复的。

ComponentActivity的成员变量_viewModelStore只会通过ComponentActivity#ensureViewModelStore方法对其进行赋值,因此看下ComponentActivity#ensureViewModelStore方法的调用点,发现除了viewModelStore属性的访问方法会调用之外,只剩下ComponentActivity的初始化代码块中调用了,具体的代码如下:

open class ComponentActivity() :
    androidx.core.app.ComponentActivity(),
    ContextAware,
    LifecycleOwner,
    ViewModelStoreOwner,
    HasDefaultViewModelProviderFactory,
    SavedStateRegistryOwner,
    OnBackPressedDispatcherOwner,
    ActivityResultRegistryOwner,
    ActivityResultCaller,
    OnConfigurationChangedProvider,
    OnTrimMemoryProvider,
    OnNewIntentProvider,
    OnMultiWindowModeChangedProvider,
    OnPictureInPictureModeChangedProvider,
    OnUserLeaveHintProvider,
    MenuHost,
    FullyDrawnReporterOwner {
    init {
		// ...
        @Suppress("LeakingThis")
        lifecycle.addObserver(
            object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    ensureViewModelStore()
                    lifecycle.removeObserver(this)
                }
            }
        )
        // ...
	}

    override val lifecycle: Lifecycle
        get() = super.lifecycle // 返回父类中的lifecycleRegistry变量

}

可以看到,在ComponentActivity的生命周期发生变化时会调用onStateChanged方法,进一步会调用ComponentActivity#ensureViewModelStore方法,因此在ComponentActivity重建之后也会调用到ComponentActivity#ensureViewModelStore方法对成员变量_viewModelStore进行赋值。

至此,明确了ComponentActivity对象的成员变量_viewModelStore对应ViewModelProviderImpl对象中的成员store。下面接着看下ViewModelProvider#get方法是如何返回自定义ViewModel的实例的。

public actual open class ViewModelProvider private constructor(
    private val impl: ViewModelProviderImpl,
) {

    @MainThread
    public open operator fun <T : ViewModel> get(modelClass: Class<T>): T =
        get(modelClass.kotlin)

    @MainThread
    public actual operator fun <T : ViewModel> get(modelClass: KClass<T>): T =
        impl.getViewModel(modelClass)

}

internal class ViewModelProviderImpl(
    private val store: ViewModelStore,
    private val factory: ViewModelProvider.Factory,
    private val extras: CreationExtras,
) {

    constructor(
        owner: ViewModelStoreOwner,
        factory: ViewModelProvider.Factory,
        extras: CreationExtras,
    ) : this(owner.viewModelStore, factory, extras)

    @Suppress("UNCHECKED_CAST")
    internal fun <T : ViewModel> getViewModel(
        modelClass: KClass<T>,
        key: String = ViewModelProviders.getDefaultKey(modelClass),
    ): T {
    	// 先从ViewModelStore中查找是否存在缓存
        val viewModel = store[key]
        // 接着判断缓存对象(如果有)的类型是否和待返回的自定义ViewModel类的类型一致,一致的话直接返回
        if (modelClass.isInstance(viewModel)) {
            if (factory is ViewModelProvider.OnRequeryFactory) {
                factory.onRequery(viewModel!!)
            }
            return viewModel as T
        } else {
            @Suppress("ControlFlowWithEmptyBody") if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        val extras = MutableCreationExtras(extras)
        extras[ViewModelProviders.ViewModelKey] = key
		// 缓存中不存在自定义ViewModel类型的对象,直接创建对象并缓存到ViewModelStore中,之后直接返回新创建的对象
        return createViewModel(factory, modelClass, extras).also { vm -> store.put(key, vm) }
    }
}

internal actual fun <VM : ViewModel> createViewModel(
    factory: ViewModelProvider.Factory,
    modelClass: KClass<VM>,
    extras: CreationExtras
): VM {
    // Android targets using `compileOnly` dependencies may encounter AGP desugaring
    // issues where `Factory.create` throws an `AbstractMethodError`. This is resolved by an
    // Android-specific implementation that first attempts all `ViewModelProvider.Factory.create`
    // method overloads before allowing the exception to propagate.
    // (See b/230454566 and b/341792251 for more details).
    return try {
        factory.create(modelClass, extras)
    } catch (e: AbstractMethodError) {
        try {
            factory.create(modelClass.java, extras)
        } catch (e: AbstractMethodError) {
            factory.create(modelClass.java)
        }
    }
}

可以看到会先从ViewModelStore查找之前是否创建过同一类型的对象,如果创建过则直接返回缓存对象,否则调用factory创建自定义ViewModel类型的对象,将其缓存到ViewModelStore中后直接返回。factory的类型是SavedStateViewModelFactory,通过SavedStateViewModelFactory#create方法可以看出最终通过反射创建了自定义ViewModel类型的对象。

class SavedStateViewModelFactory : ViewModelProvider.OnRequeryFactory, ViewModelProvider.Factory {

    override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
        val key = extras[ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY]
            ?: throw IllegalStateException(
                "VIEW_MODEL_KEY must always be provided by ViewModelProvider"
            )

        return if (extras[SAVED_STATE_REGISTRY_OWNER_KEY] != null &&
            extras[VIEW_MODEL_STORE_OWNER_KEY] != null) {
            val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]
            val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
            val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
                findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
            } else {
                findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
            }
            // doesn't need SavedStateHandle
            if (constructor == null) {
                return factory.create(modelClass, extras)
            }
            val viewModel = if (isAndroidViewModel && application != null) {
                newInstance(modelClass, constructor, application, extras.createSavedStateHandle())
            } else {
                newInstance(modelClass, constructor, extras.createSavedStateHandle())
            }
            viewModel
        } else {
            val viewModel = if (lifecycle != null) {
                create(key, modelClass)
            } else {
                throw IllegalStateException("SAVED_STATE_REGISTRY_OWNER_KEY and" +
                    "VIEW_MODEL_STORE_OWNER_KEY must be provided in the creation extras to" +
                    "successfully create a ViewModel.")
            }
            viewModel
        }
    }
}

到这里基本上梳理出ViewModel实例的获取过程:先通过ViewModelStore对象从缓存中尝试获取已创建的自定义ViewModel类型的对象,没有找到则通过反射创建自定义ViewModel类型的对象。可见,如果没有ViewModelStore的存在那么每次都会重新创建ViewModel实例,也就无法在旋转屏幕后还可以继续使用之前创建的ViewModel实例了。因此,下面重点看下ViewModelStore实例是如何在旋转屏幕之后还可以保留下来继续使用的。

2.2 ViewModelStore实例的获取

2.1节分析ViewModel实例的获取时,发现在ComponentActivity类的初始化代码块中会监听生命周期的变化,并在生命周期发生变化时调用ComponentActivity#ensureViewModelStore方法对_viewModelStore成员变量进行赋值。

open class ComponentActivity() :
    androidx.core.app.ComponentActivity(),
    ContextAware,
    LifecycleOwner,
    ViewModelStoreOwner,
    HasDefaultViewModelProviderFactory,
    SavedStateRegistryOwner,
    OnBackPressedDispatcherOwner,
    ActivityResultRegistryOwner,
    ActivityResultCaller,
    OnConfigurationChangedProvider,
    OnTrimMemoryProvider,
    OnNewIntentProvider,
    OnMultiWindowModeChangedProvider,
    OnPictureInPictureModeChangedProvider,
    OnUserLeaveHintProvider,
    MenuHost,
    FullyDrawnReporterOwner {
    init {
		// ...
        @Suppress("LeakingThis")
        lifecycle.addObserver(
            object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    ensureViewModelStore()
                    lifecycle.removeObserver(this)
                }
            }
        )
        // ...
	}

    override val lifecycle: Lifecycle
        get() = super.lifecycle // 返回父类中的lifecycleRegistry变量


    private fun ensureViewModelStore() {
        if (_viewModelStore == null) {
            val nc = lastNonConfigurationInstance as NonConfigurationInstances?
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                _viewModelStore = nc.viewModelStore
            }
            if (_viewModelStore == null) {
                _viewModelStore = ViewModelStore()
            }
        }
    }
}

可以看到在创建ViewModelStore实例之前会尝试调用Activity#getLastNonConfigurationInstance方法获取NonConfigurationInstances实例,而NonConfigurationInstances实例是在ComponentActivity#onRetainNonConfigurationInstance方法中创建并保存的。

open class ComponentActivity() :
    androidx.core.app.ComponentActivity(),
    ContextAware,
    LifecycleOwner,
    ViewModelStoreOwner,
    HasDefaultViewModelProviderFactory,
    SavedStateRegistryOwner,
    OnBackPressedDispatcherOwner,
    ActivityResultRegistryOwner,
    ActivityResultCaller,
    OnConfigurationChangedProvider,
    OnTrimMemoryProvider,
    OnNewIntentProvider,
    OnMultiWindowModeChangedProvider,
    OnPictureInPictureModeChangedProvider,
    OnUserLeaveHintProvider,
    MenuHost,
    FullyDrawnReporterOwner {
    
    @Suppress("deprecation")
    final override fun onRetainNonConfigurationInstance(): Any? {
        // Maintain backward compatibility.
        val custom = onRetainCustomNonConfigurationInstance()
        var viewModelStore = _viewModelStore
        if (viewModelStore == null) {
            // No one called getViewModelStore(), so see if there was an existing
            // ViewModelStore from our last NonConfigurationInstance
            val nc = lastNonConfigurationInstance as NonConfigurationInstances?
            if (nc != null) {
                viewModelStore = nc.viewModelStore
            }
        }
        if (viewModelStore == null && custom == null) {
            return null
        }
        val nci = NonConfigurationInstances()
        nci.custom = custom
        nci.viewModelStore = viewModelStore
        return nci
    }
}

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        ContentCaptureManager.ContentCaptureClient {
    /**
     * 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() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
            IBinder shareableActivityToken, IBinder initialCallerInfoAccessToken) {
        ...
        attachBaseContext(context);
        ...
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        ...
    }

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

}

ComponentActivity#onRetainNonConfigurationInstance方法可以看出,会将当前的_viewModelStore变量和ComponentActivity#onRetainCustomNonConfigurationInstance方法返回的对象保存到NonConfigurationInstances对象中。而Activity#onRetainNonConfigurationInstance方法会在什么时候调用,推测应该是新的Activity实例创建之前调用,这个下面会从源码层面进行确认。先看下Activity#getLastNonConfigurationInstance方法获取NonConfigurationInstances实例是在哪里赋值的,从Activity#getLastNonConfigurationInstance方法中可以发现返回结果是从Activity#mLastNonConfigurationInstances中获取的,对应Activity的静态内部类NonConfigurationInstances的成员变量activity,既然是从Activity#mLastNonConfigurationInstances中获取的,那么看下Activity#mLastNonConfigurationInstances是在哪里赋值的,从源码寻找发现是在Activity#attach方法中赋值的。了解过Activity的启动流程的同学应该知道,在创建完Activity实例之后紧接着会调用Activity#attach方法,之后才会调用Activity#onCreate等生命周期方法。

回顾一下Activity的启动流程,

public final class ActivityThread extends ClientTransactionHandler implements ActivityThreadInternal {
        
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
		...

        Activity activity = null;
        try {
            java.lang.ClassLoader cl;
            if (isSandboxedSdkContextUsed) {
                // In case of sandbox activity, the context refers to the an SDK with no visibility
                // on the SandboxedActivity java class, the App context should be used instead.
                cl = activityBaseContext.getApplicationContext().getClassLoader();
            } else {
                cl = activityBaseContext.getClassLoader();
            }
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
            ...
        }

        try {
        	...
            if (activity != null) {
            	...
                activityBaseContext.setOuterContext(activity);
                activity.attach(activityBaseContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.activityConfigCallback, r.assistToken, r.shareableActivityToken, r.initialCallerInfoAccessToken);
                ...
            }
        }
	}

}

ActivityThread#performLaunchActivity方法的实现可以发现,Activity#attach方法中的入参lastNonConfigurationInstances的值对应r.lastNonConfigurationInstances,而r就是ActivityThread#performLaunchActivity方法的类型为ActivityClientRecord的入参。因此需要再往前看下这个入参的值来自哪里,

public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
    	...
        final Activity a = performLaunchActivity(r, customIntent);
        ...
    }

    private void handleRelaunchActivityInner(@NonNull ActivityClientRecord r, @Nullable List<ResultInfo> pendingResults, @Nullable List<ReferrerIntent> pendingIntents, @NonNull PendingTransactionActions pendingActions, boolean startsNotResumed, @NonNull Configuration overrideConfig, @NonNull ActivityWindowInfo activityWindowInfo, @NonNull String reason) {
    	...
        handleDestroyActivity(r, false /* finishing */, true /* getNonConfigInstance */, reason);
        ...
    	handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent);
    }

    @Override
    public void handleRelaunchActivity(@NonNull ActivityClientRecord tmp, @NonNull PendingTransactionActions pendingActions) {
    	...
        handleRelaunchActivityInner(r, tmp.pendingResults, tmp.pendingIntents, pendingActions, tmp.startsNotResumed, tmp.overrideConfig, tmp.mActivityWindowInfo, "handleRelaunchActivity");
    }

	// 在App进程收到RELAUNCH_ACTIVITY消息之后执行此方法
    public void handleRelaunchActivityLocally(IBinder token) {
        final ActivityClientRecord r = mActivities.get(token);
        ...
        // ActivityRelaunchItem封装了重新启动Activity的逻辑,最终会调用到handleRelaunchActivity
        final ActivityRelaunchItem activityRelaunchItem = ActivityRelaunchItem.obtain(r.token, null /* pendingResults */, null /* pendingIntents */, 0 /* configChanges */, mergedConfiguration, r.mPreserveWindow, r.getActivityWindowInfo());
        // Make sure to match the existing lifecycle state in the end of the transaction.
        final ActivityLifecycleItem lifecycleRequest = TransactionExecutorHelper.getLifecycleRequestForCurrentState(r);
        // Schedule the transaction.
        final ClientTransaction transaction = ClientTransaction.obtain(mAppThread);
        transaction.addTransactionItem(activityRelaunchItem);
        transaction.addTransactionItem(lifecycleRequest);
        executeTransaction(transaction);
    }

    void performDestroyActivity(ActivityClientRecord r, boolean finishing, boolean getNonConfigInstance, String reason) {
        ...
        if (getNonConfigInstance) {
            try {
                r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException("Unable to retain activity "
                            + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
                }
            }
        }
        ...
    }

    @Override
    public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, boolean getNonConfigInstance, String reason) {
        performDestroyActivity(r, finishing, getNonConfigInstance, reason);
		...
	}
}

public class ActivityRelaunchItem extends ActivityTransactionItem {
    @Override
    public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r,
            @NonNull PendingTransactionActions pendingActions) {
        if (mActivityClientRecord == null) {
            if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled");
            return;
        }
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
        client.handleRelaunchActivity(mActivityClientRecord, pendingActions);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

向前回溯发现,当调用ActivityThread#handleRelaunchActivity重新启动Activity时,先调用ActivityThread#handleDestroyActivity方法销毁原来的Activity,然后调用ActivityThread#handleLaunchActivity启动新的Activity,在销毁旧Activity时会调用Activity#retainNonConfigurationInstances方法,进而调用Activity#onRetainNonConfigurationInstance方法获取到包含ViewModelStore实例的配置数据,并将其存放到ActivityClientRecord#lastNonConfigurationInstances中,在新Activity创建之后通过Activity#attach方法传递过去并赋值给Activity#mLastNonConfigurationInstances,这样当新Activity的生命周期开始之后就会通过注册到LifecycleRegistry的观察者,间接调用到ComponentActivity#ensureViewModelStore方法将旧ActivityViewModelStore实例赋值给新Activity进行使用了。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        ContentCaptureManager.ContentCaptureClient {
    NonConfigurationInstances retainNonConfigurationInstances() {
        Object activity = onRetainNonConfigurationInstance();
        HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();

        // We're already stopped but we've been asked to retain.
        // Our fragments are taken care of but we need to mark the loaders for retention.
        // In order to do this correctly we need to restart the loaders first before
        // handing them off to the next activity.
        mFragments.doLoaderStart();
        mFragments.doLoaderStop(true);
        ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();

        if (activity == null && children == null && fragments == null && loaders == null
                && mVoiceInteractor == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.activity = activity; // onRetainNonConfigurationInstance方法返回的数据,其中包含了ViewModelStore实例
        nci.children = children;
        nci.fragments = fragments;
        nci.loaders = loaders;
        if (mVoiceInteractor != null) {
            mVoiceInteractor.retainInstance();
            nci.voiceInteractor = mVoiceInteractor;
        }
        return nci;
    }
}

三、总结

通过源码分析之后,明确了ViewModel是在旧Activity实例调用onDestroy方法之前会调用Activity#retainNonConfigurationInstancesViewModelStore实例进行保存,并在新Activity实例创建之后通过Activity#attach方法(在Activity#onCreate方法调用之前)将ViewModelStore实例传递并赋值给新Activity实例继续使用,从而保证了ViewModel实例在横竖屏切换之后依旧能继续使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值