Known direct subclasses
ControlledRetainScope

A ControlledRetainScope is effectively a "Mutable" RetainScope.

ForgetfulRetainScope

The ForgetfulRetainScope is an implementation of RetainScope that is incapable of keeping any exited values.


A RetainScope acts as a storage area for objects being retained. An instance of a RetainScope also defines a specific retention policy to describe when removed state should be retained and when it should be forgotten.

The general pattern for retention is as follows:

  1. The RetainScope receives a notification from that transient content removal is about to begin. The source of this notification varies depending on what retention scenario is being captured, but could, for example, be a signal that an Android Activity is being recreated, or that content is about to be navigated away from/collapsed with the potential of being returned to. At this time, the scope's owner should call requestKeepExitedValues.

  2. Transient content removal begins. The content is recomposed, removed from the hierarchy, and remembered values are forgotten. Values remembered by retain leave the composition but are not yet released. Every value returned by retain will be passed as an argument to saveExitingValue so that it can later be returned by getExitedValueOrDefault.

  3. An arbitrary amount of time passes, and the removed content is restored in the composition hierarchy at its previous location. When a retain call is invoked during the restoration, it calls getExitedValueOrDefault. If all the input keys match a retained value, the previous result is returned and the retained value is removed from the pool of restorable objects that exited the previous composition. This step may be skipped if it becomes impossible to return to the transiently removed content while this scope is keeping exited values.

  4. The content finishes composing after being restored, and the entire frame completes. The owner of this scope should call unRequestKeepExitedValues. When retention stops being requested, it immediately ends. Any values that are retained and not currently used in a composition (and therefore not restored by getExitedValueOrDefault) are then immediately discarded.

A given RetainScope should only be used by a single Recomposer at a time. It can move between recomposers (for example, when the Window is recreated), but should never be used by two Recomposers simultaneously. It is valid for a RetainScope to be used in multiple compositions at the same time, or in the same composition multiple times.

Summary

Public constructors

Cmn

Public functions

final Unit

Registers the given observer with this RetainStateProvider to be notified when the value of isKeepingExitedValues changes.

Cmn
abstract Any?
getExitedValueOrDefault(key: Any, defaultIfAbsent: Any?)

If this scope is currently keeping exited values and has a value previously created with the given keys, its original record is returned and removed from the list of exited kept objects that this scope is tracking.

Cmn
final Unit

Removes a previously registered observer.

Cmn

Protected functions

abstract Unit

Called when this scope first starts to keep exited values (i.e. when isKeepingExitedValues transitions from false to true).

Cmn
abstract Unit

Called when this scope stops keeping exited values (i.e. when isKeepingExitedValues transitions from true to false).

Cmn
Unit

Called to increment the number of retain events requested.

Cmn
abstract Unit
saveExitingValue(key: Any, value: Any?)

Invoked when a retained value is exiting composition while this scope is keeping exited values.

Cmn
Unit

Clears a previous call to requestKeepExitedValues.

Cmn

Public properties

final Boolean

Returns whether the associated retain scenario is active, and associated scopes should retain objects as they are removed from the composition hierarchy.

Cmn

Public constructors

RetainScope

RetainScope()

Public functions

addRetainStateObserver

final fun addRetainStateObserver(
    observer: RetainStateProvider.RetainStateObserver
): Unit

Registers the given observer with this RetainStateProvider to be notified when the value of isKeepingExitedValues changes. The added observer will receive its first notification the next time isKeepingExitedValues is updated.

This method is not thread safe and should only be invoked on the applier thread.

getExitedValueOrDefault

abstract fun getExitedValueOrDefault(key: Any, defaultIfAbsent: Any?): Any?

If this scope is currently keeping exited values and has a value previously created with the given keys, its original record is returned and removed from the list of exited kept objects that this scope is tracking.

Parameters
key: Any

The keys to resolve a retained value that has left composition

defaultIfAbsent: Any?

A value to be returned if there are no retained values that have exited composition and are being held by this RetainScope for the given keys.

Returns
Any?

A retained value for keys if there is one and it hasn't already re-entered composition, otherwise defaultIfAbsent.

removeRetainStateObserver

final fun removeRetainStateObserver(
    observer: RetainStateProvider.RetainStateObserver
): Unit

Removes a previously registered observer. It will receive no further updates from this RetainStateProvider unless it is registered again in the future. If the observer is not currently registered, this this method does nothing.

This method is not thread safe and should only be invoked on the applier thread.

Protected functions

onStartKeepingExitedValues

protected abstract fun onStartKeepingExitedValues(): Unit

Called when this scope first starts to keep exited values (i.e. when isKeepingExitedValues transitions from false to true). When this is called, implementors should prepare to begin to store values they receive from saveExitingValue.

onStopKeepingExitedValues

protected abstract fun onStopKeepingExitedValues(): Unit

Called when this scope stops keeping exited values (i.e. when isKeepingExitedValues transitions from true to false). After this is called, all exited values that have been kept and not restored via getExitedValueOrDefault should be retired.

Implementors MUST invoke RetainObserver.onRetired for all exited and unrestored RememberObservers when this method is invoked.

requestKeepExitedValues

protected fun requestKeepExitedValues(): Unit

Called to increment the number of retain events requested. When there are a positive number of retain requests, this scope begins keeping exited values and continues until all requests are cleared.

This method is not thread safe and should only be called on the applier thread.

saveExitingValue

protected abstract fun saveExitingValue(key: Any, value: Any?): Unit

Invoked when a retained value is exiting composition while this scope is keeping exited values. It is up to the implementation of this method to decide whether and how to store these values so that they can later be retrieved by getExitedValueOrDefault.

The given keys are not guaranteed to be unique. To handle duplicate keys, implementors should return retained values with the same keys from getExitedValueOrDefault in the opposite order they are received by saveExitingValue.

If the implementation of this scope does not accept this value into its kept exited object list, it MUST call RetainObserver.onRetired if value implements RetainObserver.

unRequestKeepExitedValues

protected fun unRequestKeepExitedValues(): Unit

Clears a previous call to requestKeepExitedValues. If all retain requests have been cleared, this scope will stop keeping exited values.

This method is not thread safe and should only be called on the applier thread.

Throws
kotlin.IllegalStateException

if unRequestKeepExitedValues is called more times than requestKeepExitedValues has been called.

Public properties

isKeepingExitedValues

final val isKeepingExitedValuesBoolean

Returns whether the associated retain scenario is active, and associated scopes should retain objects as they are removed from the composition hierarchy.