前言
前面介绍了ViewModel的生命周期,知道了其会在宿主activity或者fragment销毁时被销毁(config change造成的除外);如下图:
但是没有深究其中的原理,虽然这并不影响我们的使用;但是为了知识的完成性,我们最好还是深入分析下其中的原理,同时,一些设计思想还是非常巧妙的,个人觉得是有很借鉴价值的。
分析
首先让我们回顾下ViewModel的获取方式
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
前面也说过,这其实是从创建的ViewModelProvider中得到ViewModelStore;而ViewModelStore是和宿主实例一一对应的;从ViewModelStore中获取相应classmodel对应的ViewModel实例;因此ViewModel生命周期其实是与ViewModelStore一致的;我们从这里入手进行分析,为什么config change(例如,屏幕旋转)造成的宿主销毁不会影响ViewModel的生命周期呢?
需要分开进行分析;
before androidx support activity/fragment; 参考
http://androidxref.com/8.1.0_r33/xref/frameworks/support/fragment/java/android/support/v4/app/FragmentActivity.javaandroidx support activity/fragment 参考
http://androidxref.com/9.0.0_r3/xref/frameworks/support/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
before androidx support activity/fragment宿主
当ViewModel的宿主是普通的activity或者fragment的时候,需要利用HolderFragment来保证config change时的生命周期,其原理如下
/**
* Returns the {@link ViewModelStore} of the given activity.
*
* @param activity an activity whose {@code ViewModelStore} is requested
* @return a {@code ViewModelStore}
*/
@NonNull
@MainThread
public static ViewModelStore of(@NonNull FragmentActivity activity) {
if (activity instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) activity).getViewModelStore();
}
return holderFragmentFor(activity).getViewModelStore();
}
可见;对于normal宿主,会通过holderFragmentFor(activity)返回的HolderFragment来得到ViewModelStore实例;宿主和HolderFragment一一对应;
HolderFragment
宿主对应的HolderFragment持有相应的ViewModelStore
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static HolderFragment holderFragmentFor(FragmentActivity activity) {
return sHolderFragmentManager.holderFragmentFor(activity); //返回activity宿主对应的HolderFragment
}
@SuppressWarnings("WeakerAccess")
static class HolderFragmentManager {
private Map<Activity, HolderFragment> mNotCommittedActivityHolders = new HashMap<>(); //activity对应的HolderFragment
private Map<Fragment, HolderFragment> mNotCommittedFragmentHolders = new HashMap<>();
private ActivityLifecycleCallbacks mActivityCallbacks =
new EmptyActivityLifecycleCallbacks() {
@Override
public void onActivityDestroyed(Activity activity) {
HolderFragment fragment = mNotCommittedActivityHolders.remove(activity); //activity销毁的时候remove保存的HolderFragment
if (fragment != null) {
Log.e(LOG_TAG, "Failed to save a ViewModel for " + activity);
}
}
};
private boolean mActivityCallbacksIsAdded = false;
private FragmentLifecycleCallbacks mParentDestroyedCallback =
new FragmentLifecycleCallbacks() {
@Override
public void onFragmentDestroyed(FragmentManager fm, Fragment parentFragment) {
super.onFragmentDestroyed(fm, parentFragment);
HolderFragment fragment = mNotCommittedFragmentHolders.remove(
parentFragment);
if (fragment != null) {
Log.e(LOG_TAG, "Failed to save a ViewModel for " + parentFragment);
}
}
};
void holderFragmentCreated(Fragment holderFragment) {
Fragment parentFragment = holderFragment.getParentFragment();
if (parentFragment != null) {
mNotCommittedFragmentHolders.remove(parentFragment);
parentFragment.getFragmentManager().unregisterFragmentLifecycleCallbacks(
mParentDestroyedCallback);
} else {
mNotCommittedActivityHolders.remove(holderFragment.getActivity());
}
}
private static HolderFragment findHolderFragment(FragmentManager manager) {
if (manager.isDestroyed()) {
throw new IllegalStateException("Can't access ViewModels from onDestroy");
}
Fragment fragmentByTag = manager.findFragmentByTag(HOLDER_TAG);
if (fragmentByTag != null && !(fragmentByTag instanceof HolderFragment)) {
throw new IllegalStateException("Unexpected "
+ "fragment instance was returned by HOLDER_TAG");
}
return (HolderFragment) fragmentByTag;
}
private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
HolderFragment holder = new HolderFragment();
fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
return holder;
}
HolderFragment holderFragmentFor(FragmentActivity activity) {
FragmentManager fm = activity.getSupportFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
}
if (!mActivityCallbacksIsAdded) {
mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
}
holder = createHolderFragment(fm);
mNotCommittedActivityHolders.put(activity, holder);
return holder;
}
HolderFragment holderFragmentFor(Fragment parentFragment) {
FragmentManager fm = parentFragment.getChildFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedFragmentHolders.get(parentFragment);
if (holder != null) {
return holder;
}
parentFragment.getFragmentManager()
.registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false);
holder = createHolderFragment(fm);
mNotCommittedFragmentHolders.put(parentFragment, holder);
return holder;
}
}
主要逻辑都在HolderFragmentManager中;其主要原理是利用了嵌套fragment;需要用到的一些基础知识
嵌套fragmentManager
参考https://www.cnblogs.com/mengdd/p/5552721.html
嵌套Fragment的动态添加
在宿主fragment里调用getChildFragmentManager()
即可用它来向这个fragment内部添加fragments.
Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();
同样, 对于内部的fragment来说, getParentFragment() 方法可以获取到fragment的宿主fragment.
看起来HolderFragment 是嵌套子Fragment
getChildFragmentManager() 和 getFragmentManager()
- getChildFragmentManager()是fragment中的方法, 返回的是管理当前fragment内部子fragments的manager.
- getFragmentManager()在activity和fragment中都有.
2.1 在activity中, 如果用的是v4 support库, 方法应该用getSupportFragmentManager(), 返回的是管理activity中fragments的manager;
2.2 在fragment中, 还叫getFragmentManager(), 返回的是把自己加进来的那个manager.
也即, 如果fragment在activity中, fragment.getFragmentManager()得到的是activity中管理fragments的那个manager.
2.3 如果fragment是嵌套在另一个fragment中, fragment.getFragmentManager()得到的是它的parent的getChildFragmentManager().
总结就是: getFragmentManager()是本级别管理者, getChildFragmentManager()是下一级别管理者.
这实际上是一个树形管理结构.
setRetainInstance
参考https://blog.csdn.net/gaugamela/article/details/56280384
已保留的fragment不会随着activity一起被销毁; 相反,它会一直保留(进程不消亡的前提下),并在需要时原封不动地传递给新的Activity。
当设备配置发生变化时,FragmentManager首先销毁队列中fragment的视图(因为可能有更合适的匹配资源);
紧接着,FragmentManager将检查每个fragment的retainInstance属性值。如果retainInstance属性值为false,FragmentManager会立即销毁该fragment实例。
随后,为适应新的设备配置,新的Activity的新的FragmentManager会创建一个新的fragment及其视图。
setRetainInstance原理分析
Activity遇到config change时会先保存状态
4126 /**
4127 * Calls {@link Activity#onStop()} and {@link Activity#onSaveInstanceState(Bundle)}, and updates
4128 * the client record's state.
4129 * All calls to stop an activity must be done through this method to make sure that
4130 * {@link Activity#onSaveInstanceState(Bundle)} is also executed in the same call.
4131 */
4132 private void callActivityOnStop(ActivityClientRecord r, boolean saveState, String reason) {
4133 // Before P onSaveInstanceState was called before onStop, starting with P it's
4134 // called after. Before Honeycomb state was always saved before onPause.
4135 final boolean shouldSaveState = saveState && !r.activity.mFinished && r.state == null
4136 && !r.isPreHoneycomb(); //可见自己触发finish的时候不会saveState (调用到finish的时候)
4137 final boolean isPreP = r.isPreP();
4138 if (shouldSaveState && isPreP) {
4139 callActivityOnSaveInstanceState(r);
4140 }
4141
4142 try {
4143 r.activity.performStop(false /*preserveWindow*/, reason);
4144 } catch (SuperNotCalledException e) {
4145 throw e;
4146 } catch (Exception e) {
4147 if (!mInstrumentation.onException(r.activity, e)) {
4148 throw new RuntimeException(
4149 "Unable to stop activity "
4150 + r.intent.getComponent().toShortString()
4151 + ": " + e.toString(), e);
4152 }
4153 }
4154 r.setState(ON_STOP);
4155
4156 if (shouldSaveState && !isPreP) {
4157 callActivityOnSaveInstanceState(r);
4158 }
4159 }
1435 /**
1436 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1437 * method. The default implementation simply calls through to that method.
1438 *
1439 * @param activity The activity being saved.
1440 * @param outState The bundle to pass to the call.
1441 */
1442 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1443 activity.performSaveInstanceState(outState);
1444 }
activity stop时会根据情况调用onSaveInstanceState以保存状态
/**
1574 * Called to retrieve per-instance state from an activity before being killed
1575 * so that the state can be restored in {@link #onCreate} or
1576 * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method
1577 * will be passed to both).
1578 *
1579 * <p>This method is called before an activity may be killed so that when it
1580 * comes back some time in the future it can restore its state. For example,
1581 * if activity B is launched in front of activity A, and at some point activity
1582 * A is killed to reclaim resources, activity A will have a chance to save the
1583 * current state of its user interface via this method so that when the user
1584 * returns to activity A, the state of the user interface can be restored
1585 * via {@link #onCreate} or {@link #onRestoreInstanceState}.
1586 *
1587 * <p>Do not confuse this method with activity lifecycle callbacks such as
1588 * {@link #onPause}, which is always called when an activity is being placed
1589 * in the background or on its way to destruction, or {@link #onStop} which
1590 * is called before destruction. One example of when {@link #onPause} and
1591 * {@link #onStop} is called and not this method is when a user navigates back
1592 * from activity B to activity A: there is no need to call {@link #onSaveInstanceState}
1593 * on B because that particular instance will never be restored, so the
1594 * system avoids calling it. An example when {@link #onPause} is called and
1595 * not {@link #onSaveInstanceState} is when activity B is launched in front of activity A:
1596 * the system may avoid calling {@link #onSaveInstanceState} on activity A if it isn't
1597 * killed during the lifetime of B since the state of the user interface of
1598 * A will stay intact.
1599 *
1600 * <p>The default implementation takes care of most of the UI per-instance
1601 * state for you by calling {@link android.view.View#onSaveInstanceState()} on each
1602 * view in the hierarchy that has an id, and by saving the id of the currently
1603 * focused view (all of which is restored by the default implementation of
1604 * {@link #onRestoreInstanceState}). If you override this method to save additional
1605 * information not captured by each individual view, you will likely want to
1606 * call through to the default implementation, otherwise be prepared to save
1607 * all of the state of each view yourself.
1608 *
1609 * <p>If called, this method will occur after {@link #onStop} for applications
1610 * targeting platforms starting with {@link android.os.Build.VERSION_CODES#P}.
1611 * For applications targeting earlier platform versions this method will occur
1612 * before {@link #onStop} and there are no guarantees about whether it will
1613 * occur before or after {@link #onPause}.
1614 *
1615 * @param outState Bundle in which to place your saved state.
1616 *
1617 * @see #onCreate
1618 * @see #onRestoreInstanceState
1619 * @see #onPause
1620 */
1621 protected void onSaveInstanceState(Bundle outState) {
1622 outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
1623
1624 outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
1625 Parcelable p = mFragments.saveAllState();
1626 if (p != null) {
1627 outState.putParcelable(FRAGMENTS_TAG, p);
1628 }
1629 if (mAutoFillResetNeeded) {
1630 outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
1631 getAutofillManager().onSaveInstanceState(outState);
1632 }
1633 getApplication().dispatchActivitySaveInstanceState(this, outState);
1634 }
调用到FragmentController,FragmentManager来进行保存
112 /**
113 * Saves the state for all Fragments.
114 */
115 public Parcelable saveAllState() {
116 return mHost.mFragmentManager.saveAllState(); //activity持有的fragment controller
117 }
118
2699 Parcelable saveAllState() {
2700 // Make sure all pending operations have now been executed to get
2701 // our state update-to-date.
2702 forcePostponedTransactions();
2703 endAnimatingAwayFragments();
2704 execPendingActions();
2705
2706 mStateSaved = true;
2707 mSavedNonConfig = null;
2708
2709 if (mActive == null || mActive.size() <= 0) {
2710 return null;
2711 }
2712
2713 // First collect all active fragments.
2714 int N = mActive.size();
2715 FragmentState[] active = new FragmentState[N];
2716 boolean haveFragments = false;
2717 for (int i=0; i<N; i++) {
2718 Fragment f = mActive.valueAt(i);
2719 if (f != null) {
2720 if (f.mIndex < 0) {
2721 throwException(new IllegalStateException(
2722 "Failure saving state: active " + f
2723 + " has cleared index: " + f.mIndex));
2724 }
2725
2726 haveFragments = true;
2727
2728 FragmentState fs = new FragmentState(f);
2729 active[i] = fs;
2730
2731 if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
2732 fs.mSavedFragmentState = saveFragmentBasicState(f);
2733
2734 if (f.mTarget != null) {
2735 if (f.mTarget.mIndex < 0) {
2736 throwException(new IllegalStateException(
2737 "Failure saving state: " + f
2738 + " has target not in fragment manager: " + f.mTarget));
2739 }
2740 if (fs.mSavedFragmentState == null) {
2741 fs.mSavedFragmentState = new Bundle();
2742 }
2743 putFragment(fs.mSavedFragmentState,
2744 FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
2745 if (f.mTargetRequestCode != 0) {
2746 fs.mSavedFragmentState.putInt(
2747 FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
2748 f.mTargetRequestCode);
2749 }
2750 }
2751
2752 } else {
2753 fs.mSavedFragmentState = f.mSavedFragmentState;
2754 }
2755
2756 if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
2757 + fs.mSavedFragmentState);
2758 }
2759 }
2760
2761 if (!haveFragments) {
2762 if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
2763 return null;
2764 }
2765
2766 int[] added = null;
2767 BackStackState[] backStack = null;
2768
2769 // Build list of currently added fragments.
2770 N = mAdded.size();
2771 if (N > 0) {
2772 added = new int[N];
2773 for (int i=0; i<N; i++) {
2774 added[i] = mAdded.get(i).mIndex;
2775 if (added[i] < 0) {
2776 throwException(new IllegalStateException(
2777 "Failure saving state: active " + mAdded.get(i)
2778 + " has cleared index: " + added[i]));
2779 }
2780 if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
2781 + ": " + mAdded.get(i));
2782 }
2783 }
2784
2785 // Now save back stack.
2786 if (mBackStack != null) {
2787 N = mBackStack.size();
2788 if (N > 0) {
2789 backStack = new BackStackState[N];
2790 for (int i=0; i<N; i++) {
2791 backStack[i] = new BackStackState(this, mBackStack.get(i));
2792 if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
2793 + ": " + mBackStack.get(i));
2794 }
2795 }
2796 }
2797
2798 FragmentManagerState fms = new FragmentManagerState();
2799 fms.mActive = active;
2800 fms.mAdded = added;
2801 fms.mBackStack = backStack;
2802 fms.mNextFragmentIndex = mNextFragmentIndex;
2803 if (mPrimaryNav != null) {
2804 fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
2805 }
2806 saveNonConfig();
2807 return fms;
2808 }
对所有active fragment和嵌套的fragment进行识别;如果mRetainInstance = true;则用FragmentManagerNonConfig进行保存
2604 void saveNonConfig() {
2605 ArrayList<Fragment> fragments = null;
2606 ArrayList<FragmentManagerNonConfig> childFragments = null;
2607 if (mActive != null) {
2608 for (int i=0; i<mActive.size(); i++) {
2609 Fragment f = mActive.valueAt(i);
2610 if (f != null) {
2611 if (f.mRetainInstance) {
2612 if (fragments == null) {
2613 fragments = new ArrayList<>();
2614 }
2615 fragments.add(f);
2616 f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
2617 if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
2618 }
2619 FragmentManagerNonConfig child;
2620 if (f.mChildFragmentManager != null) {
2621 f.mChildFragmentManager.saveNonConfig();
2622 child = f.mChildFragmentManager.mSavedNonConfig;
2623 } else {
2624 // f.mChildNonConfig may be not null, when the parent fragment is
2625 // in the backstack.
2626 child = f.mChildNonConfig;
2627 }
2628
2629 if (childFragments == null && child != null) {
2630 childFragments = new ArrayList<>(mActive.size());
2631 for (int j = 0; j < i; j++) {
2632 childFragments.add(null);
2633 }
2634 }
2635
2636 if (childFragments != null) {
2637 childFragments.add(child);
2638 }
2639 }
2640 }
2641 }
2642 if (fragments == null && childFragments == null) {
2643 mSavedNonConfig = null;
2644 } else {
2645 mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments);
2646 }
2647 }
将fragment对象持有住
可以看到保存fragment对象的大致逻辑; 从Activity的生命周期状态中触发,调用FragmentController->FragmentManager从而将设置了setRetainInstance(true)的fragment的相关fragment保存起来;这样config change时fragment不会执行到onDestroy; 对于HolderFragment而言,不会执行到其onDestory方法,ViewModelStore及其对应ViewModel均会得以保留
@Override
public void onDestroy() {
super.onDestroy();
mViewModelStore.clear();
}
还原的是后也是相似的路径还原的,将FragmentManagerNonConfig保存的对象还原出来,添加到相关队列里
2810 void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
2811 // If there is no saved state at all, then there can not be
2812 // any nonConfig fragments either, so that is that.
2813 if (state == null) return;
2814 FragmentManagerState fms = (FragmentManagerState)state;
2815 if (fms.mActive == null) return;
2816
2817 List<FragmentManagerNonConfig> childNonConfigs = null;
2818
2819 // First re-attach any non-config instances we are retaining back
2820 // to their saved state, so we don't try to instantiate them again.
2821 if (nonConfig != null) {
2822 List<Fragment> nonConfigFragments = nonConfig.getFragments();
2823 childNonConfigs = nonConfig.getChildNonConfigs();
2824 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
2825 for (int i = 0; i < count; i++) {
2826 Fragment f = nonConfigFragments.get(i);
2827 if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
2828 int index = 0; // index of f in fms.mActive
2829 while (index < fms.mActive.length && fms.mActive[index].mIndex != f.mIndex) {
2830 index++;
2831 }
2832 if (index == fms.mActive.length) {
2833 throwException(new IllegalStateException("Could not find active fragment "
2834 + "with index " + f.mIndex));
2835 }
2836 FragmentState fs = fms.mActive[index];
2837 fs.mInstance = f;
2838 f.mSavedViewState = null;
2839 f.mBackStackNesting = 0;
2840 f.mInLayout = false;
2841 f.mAdded = false;
2842 f.mTarget = null;
2843 if (fs.mSavedFragmentState != null) {
2844 fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
2845 f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
2846 FragmentManagerImpl.VIEW_STATE_TAG);
2847 f.mSavedFragmentState = fs.mSavedFragmentState;
2848 }
2849 }
2850 }
2851
2852 // Build the full list of active fragments, instantiating them from
2853 // their saved state.
2854 mActive = new SparseArray<>(fms.mActive.length);
2855 for (int i=0; i<fms.mActive.length; i++) {
2856 FragmentState fs = fms.mActive[i];
2857 if (fs != null) {
2858 FragmentManagerNonConfig childNonConfig = null;
2859 if (childNonConfigs != null && i < childNonConfigs.size()) {
2860 childNonConfig = childNonConfigs.get(i);
2861 }
2862 Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig);
2863 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
2864 mActive.put(f.mIndex, f);
2865 // Now that the fragment is instantiated (or came from being
2866 // retained above), clear mInstance in case we end up re-restoring
2867 // from this FragmentState again.
2868 fs.mInstance = null;
2869 }
2870 }
2871
2872 // Update the target of all retained fragments.
2873 if (nonConfig != null) {
2874 List<Fragment> nonConfigFragments = nonConfig.getFragments();
2875 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
2876 for (int i = 0; i < count; i++) {
2877 Fragment f = nonConfigFragments.get(i);
2878 if (f.mTargetIndex >= 0) {
2879 f.mTarget = mActive.get(f.mTargetIndex);
2880 if (f.mTarget == null) {
2881 Log.w(TAG, "Re-attaching retained fragment " + f
2882 + " target no longer exists: " + f.mTargetIndex);
2883 f.mTarget = null;
2884 }
2885 }
2886 }
2887 }
2888
2889 // Build the list of currently added fragments.
2890 mAdded.clear();
2891 if (fms.mAdded != null) {
2892 for (int i=0; i<fms.mAdded.length; i++) {
2893 Fragment f = mActive.get(fms.mAdded[i]);
2894 if (f == null) {
2895 throwException(new IllegalStateException(
2896 "No instantiated fragment for index #" + fms.mAdded[i]));
2897 }
2898 f.mAdded = true;
2899 if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
2900 if (mAdded.contains(f)) {
2901 throw new IllegalStateException("Already added!");
2902 }
2903 synchronized (mAdded) {
2904 mAdded.add(f);
2905 }
2906 }
2907 }
2908
2909 // Build the back stack.
2910 if (fms.mBackStack != null) {
2911 mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
2912 for (int i=0; i<fms.mBackStack.length; i++) {
2913 BackStackRecord bse = fms.mBackStack[i].instantiate(this);
2914 if (DEBUG) {
2915 Log.v(TAG, "restoreAllState: back stack #" + i
2916 + " (index " + bse.mIndex + "): " + bse);
2917 LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
2918 PrintWriter pw = new FastPrintWriter(logw, false, 1024);
2919 bse.dump(" ", pw, false);
2920 pw.flush();
2921 }
2922 mBackStack.add(bse);
2923 if (bse.mIndex >= 0) {
2924 setBackStackIndex(bse.mIndex, bse);
2925 }
2926 }
2927 } else {
2928 mBackStack = null;
2929 }
2930
2931 if (fms.mPrimaryNavActiveIndex >= 0) {
2932 mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);
2933 }
2934
2935 mNextFragmentIndex = fms.mNextFragmentIndex;
2936 }
HolderFragment相关
构造函数
public HolderFragment() {
setRetainInstance(true);
}
保持了屏幕旋转时不会调用onDestroy; 同时又持有 ViewModelStore实例对象,从而维护了其生命周期
那么activity或者fragment作为宿主如何和HolderFragment对应的呢?
normal activity bind HolderFragment
首先看activity的holderFragmentFor(activity)
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static HolderFragment holderFragmentFor(FragmentActivity activity) {
return sHolderFragmentManager.holderFragmentFor(activity);
}
HolderFragment holderFragmentFor(FragmentActivity activity) {
FragmentManager fm = activity.getSupportFragmentManager();
HolderFragment holder = findHolderFragment(fm); //在activity对应的FragmentManager找到对应的fragment(实现activity宿主和HolderFragment的一一对应)
if (holder != null) {
return holder;
}
holder = mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
}
if (!mActivityCallbacksIsAdded) {
mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
}
holder = createHolderFragment(fm); //如果没找到就通过FragmentManager添加一个
mNotCommittedActivityHolders.put(activity, holder); //并且存储一个map
return holder;
}
private static HolderFragment createHolderFragment(FragmentManager fragmentManager) {
HolderFragment holder = new HolderFragment();
fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss();
return holder;
}
相当于通过fragmentManager.add添加一个无View的HolderFragment,其持有ViewModelStore的引用,并将mRetainInstance置为true,保证了config change时的生命周期
normal fragment bind HolderFragment
HolderFragment holderFragmentFor(Fragment parentFragment) {
FragmentManager fm = parentFragment.getChildFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedFragmentHolders.get(parentFragment);
if (holder != null) {
return holder;
}
parentFragment.getFragmentManager()
.registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false);
holder = createHolderFragment(fm);
mNotCommittedFragmentHolders.put(parentFragment, holder);
return holder;
}
可见HolderFragment是宿主fragment的嵌套子fragment;
对应关系
宿主activity/fragment怎么保持和HolderFragment实例的对应关系呢?
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sHolderFragmentManager.holderFragmentCreated(this);
}
//相当于做清理工作; 每次开始前先把清理工作做了
void holderFragmentCreated(Fragment holderFragment) {
Fragment parentFragment = holderFragment.getParentFragment();
if (parentFragment != null) { //fragment作为宿主的情况
mNotCommittedFragmentHolders.remove(parentFragment);
parentFragment.getFragmentManager().unregisterFragmentLifecycleCallbacks(
mParentDestroyedCallback);
} else {
mNotCommittedActivityHolders.remove(holderFragment.getActivity());
}
}
通过mNotCommittedActivityHolders和mNotCommittedFragmentHolders进行映射,相当于一个backup缓存;HolderFragment的onCreate会进行清理(config change还原时不会走到HolderFragment的onCreate);
private ActivityLifecycleCallbacks mActivityCallbacks =
new EmptyActivityLifecycleCallbacks() {
@Override
public void onActivityDestroyed(Activity activity) {
HolderFragment fragment = mNotCommittedActivityHolders.remove(activity);
if (fragment != null) {
Log.e(LOG_TAG, "Failed to save a ViewModel for " + activity);
}
}
};
private boolean mActivityCallbacksIsAdded = false;
private FragmentLifecycleCallbacks mParentDestroyedCallback =
new FragmentLifecycleCallbacks() {
@Override
public void onFragmentDestroyed(FragmentManager fm, Fragment parentFragment) {
super.onFragmentDestroyed(fm, parentFragment);
HolderFragment fragment = mNotCommittedFragmentHolders.remove(
parentFragment);
if (fragment != null) {
Log.e(LOG_TAG, "Failed to save a ViewModel for " + parentFragment);
}
}
};
监听到宿主destory的时候会进行清理,宿主销毁时要将对应的映射也删去,清空缓存;
到此为止我们就大致明白了normal activity/fragment作为宿主时是如何保证ViewModel的生命周期的;不得不说这个设计还是很巧妙的,一个简单的fragment就实现了对ViewModelStore的维护; (我觉得这个思路值得我们借鉴,可以保存ViewModel,那是否可以保存其他东西呢? )
androidx support activity/fragment宿主 (sdkversion>=28)
因为support类型的宿主实现了ViewModelStoreOwner;所以就无需HolderFragment辅助了,而是系统内部已经帮我们实现好了;
public static ViewModelStore of(@NonNull FragmentActivity activity) {
if (activity instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) activity).getViewModelStore();
}
return holderFragmentFor(activity).getViewModelStore();
}
((ViewModelStoreOwner) activity).getViewModelStore();注意这里,直接从宿主中getViewModelStore成员变量,那么是如何保存的呢?
activity (FragmentActivity)
398 /**
399 * Destroy all fragments.
400 */
401 @Override
402 protected void onDestroy() {
403 super.onDestroy();
404
405 if (mViewModelStore != null && !isChangingConfigurations()) {
406 mViewModelStore.clear(); //对于config change造成的destory,不销毁
407 }
408
409 mFragments.dispatchDestroy(); //让管理的fragment destory
410 }
/**
* Check to see whether this activity is in the process of being destroyed in order to be
* recreated with a new configuration. This is often used in
* {@link #onStop} to determine whether the state needs to be cleaned up or will be passed
* on to the next instance of the activity via {@link #onRetainNonConfigurationInstance()}.
*
* @return If the activity is being torn down in order to be recreated with a new configuration,
* returns true; else returns false.
*/
public boolean isChangingConfigurations() {
return mChangingConfigurations;
}
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java#2497
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java#2734
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java#4595
ensureActivityConfiguration->relaunchActivityLocked-----binder call----------->handleRelaunchActivity (监听到config变化,走relaunch逻辑,将mChangingConfigurations置为true,这样Activity的ViewModelStore不会clear)
r.activity.mChangingConfigurations = true;
这里会将mViewModelStore保存下来
552 /**
553 * Retain all appropriate fragment state. You can NOT
554 * override this yourself! Use {@link #onRetainCustomNonConfigurationInstance()}
555 * if you want to retain your own state.
556 */
557 @Override
558 public final Object onRetainNonConfigurationInstance() {
559 Object custom = onRetainCustomNonConfigurationInstance();
560
561 FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
562
563 if (fragments == null && mViewModelStore == null && custom == null) {
564 return null;
565 }
566
567 NonConfigurationInstances nci = new NonConfigurationInstances();
568 nci.custom = custom;
569 nci.viewModelStore = mViewModelStore;
570 nci.fragments = fragments;
571 return nci;
572 }
会在activity 要被destory的时候将需要的东西保存下来
4410 /** Core implementation of activity destroy call. */
4411 ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
4412 int configChanges, boolean getNonConfigInstance, String reason) {
4413 ActivityClientRecord r = mActivities.get(token);
4414 Class<? extends Activity> activityClass = null;
4415 if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
4416 if (r != null) {
4417 activityClass = r.activity.getClass();
4418 r.activity.mConfigChangeFlags |= configChanges;
4419 if (finishing) {
4420 r.activity.mFinished = true;
4421 }
4422
4423 performPauseActivityIfNeeded(r, "destroy");
4424
4425 if (!r.stopped) {
4426 callActivityOnStop(r, false /* saveState */, "destroy");
4427 }
4428 if (getNonConfigInstance) {
4429 try {
4430 r.lastNonConfigurationInstances
4431 = r.activity.retainNonConfigurationInstances();
4432 } catch (Exception e) {
4433 if (!mInstrumentation.onException(r.activity, e)) {
4434 throw new RuntimeException(
4435 "Unable to retain activity "
4436 + r.intent.getComponent().toShortString()
4437 + ": " + e.toString(), e);
4438 }
4439 }
4440 }
4441 try {
4442 r.activity.mCalled = false;
4443 mInstrumentation.callActivityOnDestroy(r.activity);
4444 if (!r.activity.mCalled) {
4445 throw new SuperNotCalledException(
4446 "Activity " + safeToComponentShortString(r.intent) +
4447 " did not call through to super.onDestroy()");
4448 }
4449 if (r.window != null) {
4450 r.window.closeAllPanels();
4451 }
4452 } catch (SuperNotCalledException e) {
4453 throw e;
4454 } catch (Exception e) {
4455 if (!mInstrumentation.onException(r.activity, e)) {
4456 throw new RuntimeException(
4457 "Unable to destroy activity " + safeToComponentShortString(r.intent)
4458 + ": " + e.toString(), e);
4459 }
4460 }
4461 r.setState(ON_DESTROY);
4462 }
4463 mActivities.remove(token);
4464 StrictMode.decrementExpectedActivityCount(activityClass);
4465 return r;
4466 }
然后再onCreate的时候重新还原; mViewModelStore对象还原了,且前面又没有清掉里面保存的ViewModel对象,这样就做到了config change但是不销毁ViewModel;
317 /**
318 * Perform initialization of all fragments.
319 */
320 @SuppressWarnings("deprecation")
321 @Override
322 protected void onCreate(@Nullable Bundle savedInstanceState) {
323 mFragments.attachHost(null /*parent*/);
324
325 super.onCreate(savedInstanceState);
326
327 NonConfigurationInstances nc =
328 (NonConfigurationInstances) getLastNonConfigurationInstance();
329 if (nc != null) {
330 mViewModelStore = nc.viewModelStore;
331 }
332 if (savedInstanceState != null) {
333 Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
334 mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
335
336 // Check if there are any pending onActivityResult calls to descendent Fragments.
337 if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
338 mNextCandidateRequestIndex =
339 savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
340 int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
341 String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
342 if (requestCodes == null || fragmentWhos == null ||
343 requestCodes.length != fragmentWhos.length) {
344 Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
345 } else {
346 mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
347 for (int i = 0; i < requestCodes.length; i++) {
348 mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
349 }
350 }
351 }
352 }
353
354 if (mPendingFragmentActivityResults == null) {
355 mPendingFragmentActivityResults = new SparseArrayCompat<>();
356 mNextCandidateRequestIndex = 0;
357 }
358
359 mFragments.dispatchCreate();
360 }
activity还原过程
2304 /**
2305 * Retrieve the non-configuration instance data that was previously
2306 * returned by {@link #onRetainNonConfigurationInstance()}. This will
2307 * be available from the initial {@link #onCreate} and
2308 * {@link #onStart} calls to the new instance, allowing you to extract
2309 * any useful dynamic state from the previous instance.
2310 *
2311 * <p>Note that the data you retrieve here should <em>only</em> be used
2312 * as an optimization for handling configuration changes. You should always
2313 * be able to handle getting a null pointer back, and an activity must
2314 * still be able to restore itself to its previous state (through the
2315 * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
2316 * function returns null.
2317 *
2318 * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
2319 * {@link Fragment#setRetainInstance(boolean)} instead; this is also
2320 * available on older platforms through the Android support libraries.
2321 *
2322 * @return the object previously returned by {@link #onRetainNonConfigurationInstance()}
2323 */
2324 @Nullable
2325 public Object getLastNonConfigurationInstance() {
2326 return mLastNonConfigurationInstances != null
2327 ? mLastNonConfigurationInstances.activity : null;
2328 }
Fragment
如果宿主是fragment
1712 /**
1713 * Called when the fragment is no longer in use. This is called
1714 * after {@link #onStop()} and before {@link #onDetach()}.
1715 */
1716 @CallSuper
1717 public void onDestroy() {
1718 mCalled = true;
1719 // Use mStateSaved instead of isStateSaved() since we're past onStop()
1720 if (mViewModelStore != null && !mHost.mFragmentManager.mStateSaved) {
1721 mViewModelStore.clear();
1722 }
1723 }
也就是说就算调用了onDestory;只要mStateSaved = true,也不会清掉mViewModelStore
FragmentManager saveAllState
2936 Parcelable saveAllState() {
2937 // Make sure all pending operations have now been executed to get
2938 // our state update-to-date.
2939 forcePostponedTransactions();
2940 endAnimatingAwayFragments();
2941 execPendingActions();
2942
2943 mStateSaved = true;
2944 mSavedNonConfig = null;
2945
2946 if (mActive == null || mActive.size() <= 0) {
2947 return null;
2948 }
2949
2950 // First collect all active fragments.
2951 int N = mActive.size();
2952 FragmentState[] active = new FragmentState[N];
2953 boolean haveFragments = false;
2954 for (int i=0; i<N; i++) {
2955 Fragment f = mActive.valueAt(i);
2956 if (f != null) {
2957 if (f.mIndex < 0) {
2958 throwException(new IllegalStateException(
2959 "Failure saving state: active " + f
2960 + " has cleared index: " + f.mIndex));
2961 }
2962
2963 haveFragments = true;
2964
2965 FragmentState fs = new FragmentState(f);
2966 active[i] = fs;
2967
2968 if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
2969 fs.mSavedFragmentState = saveFragmentBasicState(f);
2970
2971 if (f.mTarget != null) {
2972 if (f.mTarget.mIndex < 0) {
2973 throwException(new IllegalStateException(
2974 "Failure saving state: " + f
2975 + " has target not in fragment manager: " + f.mTarget));
2976 }
2977 if (fs.mSavedFragmentState == null) {
2978 fs.mSavedFragmentState = new Bundle();
2979 }
2980 putFragment(fs.mSavedFragmentState,
2981 FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
2982 if (f.mTargetRequestCode != 0) {
2983 fs.mSavedFragmentState.putInt(
2984 FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
2985 f.mTargetRequestCode);
2986 }
2987 }
2988
2989 } else {
2990 fs.mSavedFragmentState = f.mSavedFragmentState;
2991 }
2992
2993 if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
2994 + fs.mSavedFragmentState);
2995 }
2996 }
2997
2998 if (!haveFragments) {
2999 if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
3000 return null;
3001 }
3002
3003 int[] added = null;
3004 BackStackState[] backStack = null;
3005
3006 // Build list of currently added fragments.
3007 N = mAdded.size();
3008 if (N > 0) {
3009 added = new int[N];
3010 for (int i = 0; i < N; i++) {
3011 added[i] = mAdded.get(i).mIndex;
3012 if (added[i] < 0) {
3013 throwException(new IllegalStateException(
3014 "Failure saving state: active " + mAdded.get(i)
3015 + " has cleared index: " + added[i]));
3016 }
3017 if (DEBUG) {
3018 Log.v(TAG, "saveAllState: adding fragment #" + i
3019 + ": " + mAdded.get(i));
3020 }
3021 }
3022 }
3023
3024 // Now save back stack.
3025 if (mBackStack != null) {
3026 N = mBackStack.size();
3027 if (N > 0) {
3028 backStack = new BackStackState[N];
3029 for (int i=0; i<N; i++) {
3030 backStack[i] = new BackStackState(mBackStack.get(i));
3031 if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
3032 + ": " + mBackStack.get(i));
3033 }
3034 }
3035 }
3036
3037 FragmentManagerState fms = new FragmentManagerState();
3038 fms.mActive = active;
3039 fms.mAdded = added;
3040 fms.mBackStack = backStack;
3041 if (mPrimaryNav != null) {
3042 fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
3043 }
3044 fms.mNextFragmentIndex = mNextFragmentIndex;
3045 saveNonConfig();
3046 return fms;
3047 }
2829 void saveNonConfig() {
2830 ArrayList<Fragment> fragments = null;
2831 ArrayList<FragmentManagerNonConfig> childFragments = null;
2832 ArrayList<ViewModelStore> viewModelStores = null;
2833 if (mActive != null) {
2834 for (int i=0; i<mActive.size(); i++) {
2835 Fragment f = mActive.valueAt(i);
2836 if (f != null) {
2837 if (f.mRetainInstance) {
2838 if (fragments == null) {
2839 fragments = new ArrayList<Fragment>();
2840 }
2841 fragments.add(f);
2842 f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
2843 if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
2844 }
2845 FragmentManagerNonConfig child;
2846 if (f.mChildFragmentManager != null) {
2847 f.mChildFragmentManager.saveNonConfig();
2848 child = f.mChildFragmentManager.mSavedNonConfig;
2849 } else {
2850 // f.mChildNonConfig may be not null, when the parent fragment is
2851 // in the backstack.
2852 child = f.mChildNonConfig;
2853 }
2854
2855 if (childFragments == null && child != null) {
2856 childFragments = new ArrayList<>(mActive.size());
2857 for (int j = 0; j < i; j++) {
2858 childFragments.add(null);
2859 }
2860 }
2861
2862 if (childFragments != null) {
2863 childFragments.add(child);
2864 }
2865 if (viewModelStores == null && f.mViewModelStore != null) {
2866 viewModelStores = new ArrayList<>(mActive.size());
2867 for (int j = 0; j < i; j++) {
2868 viewModelStores.add(null);
2869 }
2870 }
2871
2872 if (viewModelStores != null) {
2873 viewModelStores.add(f.mViewModelStore);
2874 }
2875 }
2876 }
2877 }
2878 if (fragments == null && childFragments == null && viewModelStores == null) {
2879 mSavedNonConfig = null;
2880 } else {
2881 mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments,
2882 viewModelStores); //将要保存的东西都存到FragmentManagerNonConfig,相比上面多加了一个mViewModelStore
//包括三部分:不被销毁的Fragment集合(通过setRetainInstance(true)),所有子Fragment中需要保存的数据以及所有的Fragment中的ViewModelStore
2883 }
2884 }
所以宿主fragment不设定setRetainInstance也没关系,因为fragment销毁了但是其mViewModelStore并没有销毁;而是被保存起来了
fragment还原ViewModel过程
1461 /**
1462 * Called to do initial creation of a fragment. This is called after
1463 * {@link #onAttach(Activity)} and before
1464 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
1465 *
1466 * <p>Note that this can be called while the fragment's activity is
1467 * still in the process of being created. As such, you can not rely
1468 * on things like the activity's content view hierarchy being initialized
1469 * at this point. If you want to do work once the activity itself is
1470 * created, see {@link #onActivityCreated(Bundle)}.
1471 *
1472 * <p>Any restored child fragments will be created before the base
1473 * <code>Fragment.onCreate</code> method returns.</p>
1474 *
1475 * @param savedInstanceState If the fragment is being re-created from
1476 * a previous saved state, this is the state.
1477 */
1478 @CallSuper
1479 public void onCreate(@Nullable Bundle savedInstanceState) {
1480 mCalled = true;
1481 restoreChildFragmentState(savedInstanceState);
1482 if (mChildFragmentManager != null
1483 && !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) {
1484 mChildFragmentManager.dispatchCreate();
1485 }
1486 }
1488 /**
1489 * Restore the state of the child FragmentManager. Called by either
1490 * {@link #onCreate(Bundle)} for non-retained instance fragments or by
1491 * {@link FragmentManagerImpl#moveToState(Fragment, int, int, int, boolean)}
1492 * for retained instance fragments.
1493 *
1494 * <p><strong>Postcondition:</strong> if there were child fragments to restore,
1495 * the child FragmentManager will be instantiated and brought to the {@link #CREATED} state.
1496 * </p>
1497 *
1498 * @param savedInstanceState the savedInstanceState potentially containing fragment info
1499 */
1500 void restoreChildFragmentState(@Nullable Bundle savedInstanceState) {
1501 if (savedInstanceState != null) {
1502 Parcelable p = savedInstanceState.getParcelable(
1503 FragmentActivity.FRAGMENTS_TAG);
1504 if (p != null) {
1505 if (mChildFragmentManager == null) {
1506 instantiateChildFragmentManager();
1507 }
1508 mChildFragmentManager.restoreAllState(p, mChildNonConfig);
1509 mChildNonConfig = null;
1510 mChildFragmentManager.dispatchCreate();
1511 }
1512 }
1513 }
3049 void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
3050 // If there is no saved state at all, then there can not be
3051 // any nonConfig fragments either, so that is that.
3052 if (state == null) return;
3053 FragmentManagerState fms = (FragmentManagerState)state;
3054 if (fms.mActive == null) return;
3055
3056 List<FragmentManagerNonConfig> childNonConfigs = null;
3057 List<ViewModelStore> viewModelStores = null;
3058
3059 // First re-attach any non-config instances we are retaining back
3060 // to their saved state, so we don't try to instantiate them again.
3061 if (nonConfig != null) {
3062 List<Fragment> nonConfigFragments = nonConfig.getFragments();
3063 childNonConfigs = nonConfig.getChildNonConfigs();
3064 viewModelStores = nonConfig.getViewModelStores();
3065 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
3066 for (int i = 0; i < count; i++) {
3067 Fragment f = nonConfigFragments.get(i);
3068 if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
3069 int index = 0; // index into fms.mActive
3070 while (index < fms.mActive.length && fms.mActive[index].mIndex != f.mIndex) {
3071 index++;
3072 }
3073 if (index == fms.mActive.length) {
3074 throwException(new IllegalStateException("Could not find active fragment "
3075 + "with index " + f.mIndex));
3076 }
3077 FragmentState fs = fms.mActive[index];
3078 fs.mInstance = f;
3079 f.mSavedViewState = null;
3080 f.mBackStackNesting = 0;
3081 f.mInLayout = false;
3082 f.mAdded = false;
3083 f.mTarget = null;
3084 if (fs.mSavedFragmentState != null) {
3085 fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
3086 f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
3087 FragmentManagerImpl.VIEW_STATE_TAG);
3088 f.mSavedFragmentState = fs.mSavedFragmentState;
3089 }
3090 }
3091 }
3092
3093 // Build the full list of active fragments, instantiating them from
3094 // their saved state.
3095 mActive = new SparseArray<>(fms.mActive.length);
3096 for (int i=0; i<fms.mActive.length; i++) {
3097 FragmentState fs = fms.mActive[i];
3098 if (fs != null) {
3099 FragmentManagerNonConfig childNonConfig = null;
3100 if (childNonConfigs != null && i < childNonConfigs.size()) {
3101 childNonConfig = childNonConfigs.get(i);
3102 }
3103 ViewModelStore viewModelStore = null;
3104 if (viewModelStores != null && i < viewModelStores.size()) {
3105 viewModelStore = viewModelStores.get(i);
3106 }
3107 Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig,
3108 viewModelStore);
3109 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
3110 mActive.put(f.mIndex, f);
3111 // Now that the fragment is instantiated (or came from being
3112 // retained above), clear mInstance in case we end up re-restoring
3113 // from this FragmentState again.
3114 fs.mInstance = null;
3115 }
3116 }
3117
3118 // Update the target of all retained fragments.
3119 if (nonConfig != null) {
3120 List<Fragment> nonConfigFragments = nonConfig.getFragments();
3121 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
3122 for (int i = 0; i < count; i++) {
3123 Fragment f = nonConfigFragments.get(i);
3124 if (f.mTargetIndex >= 0) {
3125 f.mTarget = mActive.get(f.mTargetIndex);
3126 if (f.mTarget == null) {
3127 Log.w(TAG, "Re-attaching retained fragment " + f
3128 + " target no longer exists: " + f.mTargetIndex);
3129 }
3130 }
3131 }
3132 }
3133
3134 // Build the list of currently added fragments.
3135 mAdded.clear();
3136 if (fms.mAdded != null) {
3137 for (int i=0; i<fms.mAdded.length; i++) {
3138 Fragment f = mActive.get(fms.mAdded[i]);
3139 if (f == null) {
3140 throwException(new IllegalStateException(
3141 "No instantiated fragment for index #" + fms.mAdded[i]));
3142 }
3143 f.mAdded = true;
3144 if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
3145 if (mAdded.contains(f)) {
3146 throw new IllegalStateException("Already added!");
3147 }
3148 synchronized (mAdded) {
3149 mAdded.add(f);
3150 }
3151 }
3152 }
3153
3154 // Build the back stack.
3155 if (fms.mBackStack != null) {
3156 mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
3157 for (int i=0; i<fms.mBackStack.length; i++) {
3158 BackStackRecord bse = fms.mBackStack[i].instantiate(this);
3159 if (DEBUG) {
3160 Log.v(TAG, "restoreAllState: back stack #" + i
3161 + " (index " + bse.mIndex + "): " + bse);
3162 LogWriter logw = new LogWriter(TAG);
3163 PrintWriter pw = new PrintWriter(logw);
3164 bse.dump(" ", pw, false);
3165 pw.close();
3166 }
3167 mBackStack.add(bse);
3168 if (bse.mIndex >= 0) {
3169 setBackStackIndex(bse.mIndex, bse);
3170 }
3171 }
3172 } else {
3173 mBackStack = null;
3174 }
3175
3176 if (fms.mPrimaryNavActiveIndex >= 0) {
3177 mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);
3178 }i
3179 this.mNextFragmentIndex = fms.mNextFragmentIndex;
3180 }
这里其实看起来复杂,但和androidx 的Activity保存ViewModelStore的原理类似;都是让他正常销毁;然后保存
总结
本问总结了ViewModel在config change时保持生命周期的相关原理;分为两种情况:
- before androidx support activity/fragment
利用无View的HolderFragment,使用setRetainInstance(true)保证其在config change时不被销毁;这个思路值得我们借鉴 - androidx support activity/fragment
在系统层进行了适配,无需HolderFragment接入了,其原理是config change正常执行销毁工作,只不过在再次relaunch时还原;
虽然保存/还原的代码看上去类似,但其实是两种不同的原理,尤其要注意利用HolderFragment的兼容性适配工作,其实一种巧妙的设计思路,只有对aosp源码,activity/fragment生命周期,交互有较深了解的人才能进行这样巧妙的设计,值得我们学习