SavedStateHandle

原理图

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

Demo

// 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
   ...
)

performSave

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);
}

performRestore

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

SavedStateViewModelFactory

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);
    }
}

SavedStateRegistryOwner

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();
}

SavedStateRegistryController

/**
 * 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;
}

SavedStateRegistry

/**
 * 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();
    }
}