【安卓开发系列 -- APP】JetPack -- SavedState

【1】SavedState 概念

SavedState 是为了弥补 ViewModel 无法直接感知 onSaveInstanceState 被触发的时机的缺陷而产生的;
在页面即将被销毁的时候,每个使用 SavedState 的 ViewModel 都会创建一个 Bundle 来存储自己的这份数据,最后这些 Bundle 会被汇总到一个 Bundle 中,然后再保存到 onSaveInstanceState(Bundle outState) 的 outState 中;
当页面恢复的时候,会从 onCreate(Bundle savedInstanceState) 中的 savedInstanceState 中取出原来存放的总的那个 Bundle,然后再取出一个个的属于 ViewModel 的子 Bundle,从而实现在 ViewModel 中复用之前存储的数据;
其实就是利用 Bundle 可以保存另一个 Bundle 这么一个特点,分层分区保存数据,让数据之间相互分离,进而方便整存整取;

【2】SavedState 使用示例 -- ViewModel 搭配 SavedState 实现数据复用

核心思想
当 Activity 的 onSaveInstanceState 方法被执行的时候,会触发 SavedStateHandle 的 Bundle saveState()  方法,从而保存其数据;当 Activity 被恢复的时候,在新建 ViewModel 实例对象的时候,会从 Activity 的 savedInstanceState  中提取之前存储数据,然后构造 SavedStateHandle 对象并把恢复的数据赋值给该对象,随后把 SavedStateHandle 传递到 ViewModel 中,从而复用其数据;

class SavedStateViewModel extends ViewModel {
    // 需要引用 SavedStateHandle
    private SavedStateHandle mHandle;

    public SavedStateViewModel(SavedStateHandle handle) {
        mHandle = handle;
        // 实现数据的恢复
        Object text = mHandle.get("text");
        if (null == text) {
            String time = String.valueOf(System.currentTimeMillis() / 1000);
            // 实现数据的保存
            mHandle.set("text", time);
            QrLog.e("SavedStateViewModel 初始化数据 = " + time);
        } else {
            QrLog.e("SavedStateViewModel 恢复数据 = " + text);
        }
    }
}

// ViewModelActivity.java
class ViewModelActivity extends AppCompatActivity {
    SavedStateViewModel mSavedStateViewModel;
    void onCreate(Bundle savedInstanceState) {
        // 这边创建时传入了 SavedStateViewModelFactory
        mSavedStateViewModel = ViewModelProviders
            .of(this, new SavedStateViewModelFactory(getApplication(), this))
            .get(SavedStateViewModel.class);
        QrLog.e("mSavedStateViewModel hashCode = " + mSavedStateViewModel.hashCode());
    }
}

【3】SavedState 相关源码分析

SavedState 涉及的类结构图及其中的组成成员

Save Images安卓版 savefrom安卓版_ide

**SavedStateRegistryOwner:**接口,用于获取 SavedStatedRegistry 对象;
SavedStateRegistryController:用于创建 SavedStatedRegistry,用于连接 Activity\Fragment 和 SavedStatedRegistry;
SavedStatedRegistry:数据存储、恢复中心;
SavedStateHandleController:用于从数据中心提出数据并创建 SavedStateHandle;
SavedStateHandle:单个 ViewModel 用于数据存储和恢复的对象;

SavedStateRegistry 模型图示

一个总 Bundle ,以 key-value 形式存储着每个 ViewModel 对应的子 Bundle;

Save Images安卓版 savefrom安卓版_复用_02

SavedState 数据存储流程
逐一调用每个 SavedStateHandle 保存自己的数据,汇总成一个总的 Bundle,再存储到 Activity 的 savedState 对象中;

Save Images安卓版 savefrom安卓版_复用_03

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

    // public class LifecycleRegistry extends Lifecycle
    // 绑定了生命周期
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    private final SavedStateRegistryController mSavedStateRegistryController =
        SavedStateRegistryController.create(this);

    // 页面失去焦点时被系统调用
    @CallSuper
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Lifecycle lifecycle = getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            // 更新 Lifecycle 的状态信息
            ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
        }
        // 调用父类的 onSaveInstanceState
        super.onSaveInstanceState(outState);
        // 调用 performSave 转发给 SavedStateRegistryController
        // outState 为 Activity 层面的 Bundle 实例
        mSavedStateRegistryController.performSave(outState);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

}
public final class SavedStateRegistryController {

    private final SavedStateRegistry mRegistry;

    @MainThread
    public void performSave(@NonNull Bundle outBundle) {
        // 直接转发给 SavedStateRegistry
        mRegistry.performSave(outBundle);
    }

    // 创建一个 SavedStateRegistryController 实例
    @NonNull
    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }

}
public final class SavedStateRegistry {

    // 用于保存 SavedStateProvider 实例
    private SafeIterableMap<String, SavedStateProvider> mComponents =
            new SafeIterableMap<>();

    // 总的 Bundle 对象
    // 当前 SavedStateRegistry 保存的数据
    private Bundle mRestoredState;

    @MainThread
    void performSave(@NonNull Bundle outBundle) {
        // 新建一个 Bundle 对象
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            // 若 mRestoredState 存在则将新建的 components 存入其中
            /**
             * Inserts all mappings from the given Bundle into this Bundle.
             */
            components.putAll(mRestoredState);
        }
        // 遍历所有注册的 SavedStateProvider 的 saveState() 方法保存各自的数据
        for (Iterator<Map.Entry<String, SavedStateProvider>> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry<String, SavedStateProvider> entry1 = it.next();
            /**
             * Inserts a Bundle value into the mapping of this Bundle, replacing
             * any existing value for the given key.  Either key or value may be null.
             */
            // 将每个 SavedStateHandle 返回的 bundle 汇总到 components 中
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        /**
         * Inserts a Bundle value into the mapping of this Bundle, replacing
         * any existing value for the given key.  Either key or value may be null.
         */
        // 将 components 存储到 outBundle 中
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }

}

SavedStateHandle 参数传递到 ViewModel 的流程 -- SavedState 数据复用流程

提取出存储的 Bundle 数据对象流程

Save Images安卓版 savefrom安卓版_Save Images安卓版_04

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

    private final SavedStateRegistryController mSavedStateRegistryController =
            SavedStateRegistryController.create(this);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 页面新建时派发给 SavedStateRegistryController
        mSavedStateRegistryController.performRestore(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }

}
public final class SavedStateRegistryController {

    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;

    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
        mOwner = owner; // mOwner 的值在 create 方法中由调用对象传入
        mRegistry = new SavedStateRegistry();
    }

    @MainThread
    public void performRestore(@Nullable Bundle savedState) {
        // 获取 Lifecycle 实例
        Lifecycle lifecycle = mOwner.getLifecycle();
        // 判断 Lifecycle 实例的状态是否正确
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
        // 建立生命周期观察者
        // Recreator 实现了 GenericLifecycleObserver(扩展了 LifecycleEventObserver) 接口
        // Recreator 提供了内部静态 final 类 SavedStateProvider 用于提供 SsavedStateHandle
        lifecycle.addObserver(new Recreator(mOwner));
        // 转发给 SavedStateRegistry 处理
        mRegistry.performRestore(lifecycle, savedState);
    }

    // 创建一个 SavedStateRegistryController 实例
    @NonNull
    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }

}
public final class SavedStateRegistry {

    // 用于标记保存的状态是否已经恢复
    private boolean mRestored;
    // 用于标记是否允许进行数据存储操作
    boolean mAllowingSavingState = true;

    @MainThread
    void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
        // 确保保存状态的恢复只能进行一次
        if (mRestored) {
            throw new IllegalStateException("SavedStateRegistry was already restored.");
        }
        if (savedState != null) {
            // 获取当前页面存储数据的 bundle 集合
            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
        }

        // 为 Lifecycle 实例添加新的观察者
        lifecycle.addObserver(new GenericLifecycleObserver() {
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_START) {
                    mAllowingSavingState = true;
                } else if (event == Lifecycle.Event.ON_STOP) {
                    mAllowingSavingState = false;
                }
            }
        });

        mRestored = true;
    }

}

Bundle 数据对象的复用流程

创建 ViewModel 实例时,会从 SavedStateRegistry 获取当前 ViewModel 之前存储的数据并赋值给 SavedStateHandle 对象,并将 savedSateHandle 以参数的形式传递到 ViewModel 完成复用;

Save Images安卓版 savefrom安卓版_ide_05

public class ViewModelProvider {

    // 这里会判断 Activity/Fragment 是不是 HasDefaultViewModelProviderFactory 类型
    // 若 Activity/Fragment 都实现了 HasDefaultViewModelProviderFactory 接口,
    // 则当调用这个构造函数创建 ViewModelProvider 获取 ViewModel 的时候
    // 都是由 SavedStateViewModelFactory 负责具体的创建以及参数传递的
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

}
public interface HasDefaultViewModelProviderFactory {

    // 提供方法用于获取默认的 ViewModelProviderFactory 实例
    @NonNull
    ViewModelProvider.Factory getDefaultViewModelProviderFactory();
}

// ComponentActivity 实现了 HasDefaultViewModelProviderFactory 接口
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

    private ViewModelProvider.Factory mDefaultFactory;

    // 覆写了 HasDefaultViewModelProviderFactory 接口的 getDefaultViewModelProviderFactory 方法
    @NonNull
    @Override
    public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
        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 (mDefaultFactory == null) {
            // 此处新建了 SavedStateViewModelFactory 实例并返回
            mDefaultFactory = new SavedStateViewModelFactory(
                    getApplication(),
                    this,
                    getIntent() != null ? getIntent().getExtras() : null);
        }
        return mDefaultFactory;
    }
        
}
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {

    private final Bundle mDefaultArgs;
    private final Lifecycle mLifecycle;
    private final SavedStateRegistry mSavedStateRegistry;
    private final ViewModelProvider.AndroidViewModelFactory mFactory;

    // SavedStateViewModelFactory 创建 ViewMdodel 实例的方法
    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        // 1. 判断 viewmodel 是不是 AndroidViewModel 的子类
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
        if (isAndroidViewModel) {
            // 2. 如果是 AndroidViewModel 的子类,
            // 则尝试查找其是否拥有(Application, SavedStateHandle)两个参数的构造函数
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            // 3. 如果不是 AndroidViewModel 的子类,
            // 则查找其是否拥有(SavedStateHandle)一个参数的构造函数
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        // doesn't need SavedStateHandle
        if (constructor == null) {
            // 4. 若上面两种方式都没找到相应的构造函数,则说明该 viewmodel 没有声明以上两种类型
            // 此时使用 AndroidViewModelFactory 创建 viewmodel 实例
            return mFactory.create(modelClass);
        }
        // 5. 执行到此处,则说明构造函数上存在 savedSateHandle 参数
        // 这里会首先构建出 SavedStateHandleController 对象
        // SavedStateHandleController 类的作用是从 SavedStateRegistry 
        // 提取出该 ViewModel 的 Bundle 数据对象,从而创建 savedSateHandle 对象
        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
            // 反射创建 ViewModel 对象并传递 SavedStateHandle 对象
            if (isAndroidViewModel) {
                // 带参数的反射构造 ViewModel 实例对象
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                // 没有参数的反射构造 ViewModel 实例对象
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            /**
             * Sets a tag associated with this viewmodel and a key
             */
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            // 返回新创建的 ViewModel 实例对象
            return viewmodel;
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to access " + modelClass, e);
        } catch (InstantiationException e) {
            throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("An exception happened in constructor of "
                    + modelClass, e.getCause());
        }
    }

}
final class SavedStateHandleController implements LifecycleEventObserver {

    private final SavedStateHandle mHandle;

    static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {

        // 从数据中心 SavedStateRegistry 提出该 ViewModel 的 Bundle 数据对象
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        // 构建 SavedStateHandle 对象,并把 restoredState 中的数据再拆分出来,存储到 mRegular 这个 map 集合中
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
        // 新建 SavedStateHandleController 实例
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
        // 将 SavedStateHandleController 实例与宿主的生命周期关联
        controller.attachToLifecycle(registry, lifecycle);
        // 添加重新创建器
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

    SavedStateHandle getHandle() {
        return mHandle;
    }

}

附录

Android 生命周期各个方法之间的调用关系图

Save Images安卓版 savefrom安卓版_复用_06

参考
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】跟架构师学Jetpack

【2】Android-Jetpack笔记-ViewModelSavedState