sequenceDiagram
ComponentActivity->>ComponentActivity: onSaveInstanceState
activate ComponentActivity
ComponentActivity->>SavedStateRegistryController: performSave
activate SavedStateRegistryController
SavedStateRegistryController->>SavedStateRegistry: performSave
deactivate SavedStateRegistryController
deactivate ComponentActivity
ComponentActivity->>ComponentActivity: onCreate
activate ComponentActivity
ComponentActivity->>SavedStateRegistryController: performRestore
activate SavedStateRegistryController
SavedStateRegistryController->>SavedStateRegistry: performRestore
deactivate SavedStateRegistryController
deactivate ComponentActivity
SavedStateViewModelFactory->>SavedStateViewModelFactory: create
activate SavedStateViewModelFactory
SavedStateViewModelFactory->>SavedStateHandleController: create
SavedStateHandleController->>SavedStateRegistry: consumeRestoredStateForKey
SavedStateRegistry->>SavedStateHandle: createHandle
deactivate SavedStateViewModelFactory
// UserProfileViewModel
class UserProfileViewModel(
savedStateHandle: SavedStateHandle
) : ViewModel() {
val userId : String = savedStateHandle["uid"] ?:
throw IllegalArgumentException("missing user id")
val user : User = TODO()
}
// UserProfileFragment
private val viewModel: UserProfileViewModel by viewModels(
factoryProducer = { SavedStateViewModelFactory(this) } //新版这已经是by viewModels的默认factory
...
)
ComponentActivity
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Lifecycle lifecycle = getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
}
super.onSaveInstanceState(outState);
mSavedStateRegistryController.performSave(outState);//main
}
public void performSave(@NonNull Bundle outBundle) {
mRegistry.performSave(outBundle);
}
void performSave(@NonNull Bundle outBundle) {
Bundle components = new Bundle();
if (mRestoredState != null) {
components.putAll(mRestoredState);
}
for (Iterator<Map.Entry<String, SavedStateProvider>> it =
mComponents.iteratorWithAdditions(); it.hasNext(); ) {
Map.Entry<String, SavedStateProvider> entry1 = it.next();
components.putBundle(entry1.getKey(), entry1.getValue().saveState());
}
outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}
ComponentActivity.onSaveInstanceState
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
public void performRestore(@Nullable Bundle savedState) {
Lifecycle lifecycle = mOwner.getLifecycle();
if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
throw new IllegalStateException("Restarter must be created only during "
+ "owner's initialization stage");
}
lifecycle.addObserver(new Recreator(mOwner));
mRegistry.performRestore(lifecycle, savedState);
}
void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
if (mRestored) {
throw new IllegalStateException("SavedStateRegistry was already restored.");
}
if (savedState != null) {
mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
}
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;
}
https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
public SavedStateViewModelFactory(@NonNull Application application,
@NonNull SavedStateRegistryOwner owner) {
this(application, owner, null);
}
public SavedStateViewModelFactory(@NonNull Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
}
public interface SavedStateRegistryOwner extends LifecycleOwner {
@NonNull
SavedStateRegistry getSavedStateRegistry();
}
ComponentActivity implement SavedStateRegistryOwner
private final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
@NonNull
@Override
public final SavedStateRegistry getSavedStateRegistry() {
return mSavedStateRegistryController.getSavedStateRegistry();
}
/**
* An API for {@link SavedStateRegistryOwner} implementations to control {@link SavedStateRegistry}.
* <p>
* {@code SavedStateRegistryOwner} should call {@link #performRestore(Bundle)} to restore state of
* {@link SavedStateRegistry} and {@link #performSave(Bundle)} to gather SavedState from it.
*/
public final class SavedStateRegistryController {
private final SavedStateRegistryOwner mOwner;
private final SavedStateRegistry mRegistry;
private SavedStateRegistryController(SavedStateRegistryOwner owner) {
mOwner = owner;
mRegistry = new SavedStateRegistry();
}
@NonNull
public SavedStateRegistry getSavedStateRegistry() {
return mRegistry;
}
/**
* An interface for plugging components that consumes and contributes to the saved state.
*
* <p>This objects lifetime is bound to the lifecycle of owning component: when activity or
* fragment is recreated, new instance of the object is created as well.
*/
public final class SavedStateRegistry {
@Nullable
private Bundle mRestoredState;
private SafeIterableMap<String, SavedStateProvider> mComponents =
new SafeIterableMap<>();
public Bundle consumeRestoredStateForKey(@NonNull String key) {
if (mRestoredState != null) {
Bundle result = mRestoredState.getBundle(key);
mRestoredState.remove(key);
if (mRestoredState.isEmpty()) {
mRestoredState = null;
}
return result;
}
return null;
}
public void registerSavedStateProvider(@NonNull String key,
@NonNull SavedStateProvider provider) {
SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
if (previous != null) {
throw new IllegalArgumentException("SavedStateProvider with the given key is"
+ " already registered");
}
}
/**
* This interface marks a component that contributes to saved state.
*/
public interface SavedStateProvider {
/**
* Called to retrieve a state from a component before being killed
* so later the state can be received from {@link #consumeRestoredStateForKey(String)}
*
* @return S with your saved state.
*/
@NonNull
Bundle saveState();
}
}