useCached

fun <T> ComponentScope.useCached(vararg inputs: Any?, calculator: () -> T): T

Create a CachedValue variable within a Component. The calculator will provide the calculated value if it hasn't already been calculated or if the inputs have changed since the previous calculation.

Lifetime: a cached value can outlive the ComponentTree that created it

Cached values are stored in the TreeState of the enclosing ComponentTree and have no pruning path: unlike state, which StateHandler.clearUnusedState drops once a component leaves the tree, cached values are copied forward verbatim into every subsequent StateHandler.

Inside a collection this is compounded by the fact that a row's TreeState is deliberately retained when the row leaves the prepared range, so that state can be restored on scroll-back (RecyclerBinder.Builder.acquireStateHandlerOnRelease defaults to true, and LithoRenderer.cleanup does not clear treeState). A cached value therefore survives release of the row's ComponentTree and is only freed when the collection's data set is replaced: retention grows with the number of rows ever scrolled past, not the number of rows on screen. The same applies to a value cached by a throwaway component built only to measure, since Component.measure resolves against the enclosing TreeState.

Because of this, do not cache objects that are expensive to retain — inflated animation graphs, bitmaps, view hierarchies, anything holding native memory — in a component that can appear in a collection item. For those, either recompute per render, or hold the object in a bounded, evicting cache owned outside the tree and cache only a cheap key here.