WhileUsed

class WhileUsed<T>(retentionMillis: Long = 0, destructor: (T) -> Unit? = null, builder: (WhileUsedReferenceToken) -> T)

A reference-counted value that is created on-demand and freed once nobody uses it (whereas by lazy is never freed).

WhileUsed is useful for e.g. caches or other resource-consuming values that shouldn't live forever, but only exist while they're in use. Sometimes this can also be helpful for dealing with security-critical data.

This can be a great combination with SharingStarted.WhileSubscribed and either derived or Flow.stateIn/Flow.shareIn, for example.

In order to request the value with invoke you need a CoroutineScope or a DisposableGroup. Note: Your builder function is also passed a DisposableGroup for accessing other WhileUsed instances. The CoroutineScope/DisposableGroup is used to track the requester's lifetime and in turn the reference count. As an alternative when you don't have a CoroutineScope you can also use disposableValue, but this is more error-prone because it's easier to forget.

Typically you'd place such values in your DI system and have one or more ViewModels or UI screens or widgets requesting the value. Once these screens/widgets/ViewModels are destroyed (e.g. because the user pressed on the back button) the value is freed again.

Example:

val createDatabase = WhileUsed { Database() }
val createCache = WhileUsed { DbCache(createDatabase(it)) }

class MyViewModel : ViewModel() {
val cache = createCache(viewModelScope)
}

Parameters

retentionMillis

Defines a retention period in milliseconds in which to still keep the value in RAM although the reference count returned to 0. If the value is requested again within this retention period, the old value is reused. Defaults to 0 (immediately frees the value).

destructor

Optional destructor which can clean up the object before it gets freed. Defaults to null in which case, if the value is a Disposable, its dispose() method is called. Pass an empty lambda function if you don't want this behavior.

builder

Should create and return the value. The builder gets a DisposableGroup as its argument for retrieving other WhileUsed values or for adding other Disposables which must be cleaned up together with this value (as an alternative to using destructor).

Constructors

Link copied to clipboard
constructor(retentionMillis: Long = 0, destructor: (T) -> Unit? = null, builder: (WhileUsedReferenceToken) -> T)

Functions

Link copied to clipboard

Creates or returns the existing value while incrementing the reference count. You really want invoke instead.

Link copied to clipboard
operator fun invoke(referenceToken: DisposableGroup): T
operator fun invoke(userScope: CoroutineScope): T

Creates or returns the existing value while incrementing the reference count.