Does Jetpack Compose automatically clear lambda captures when a composable exits the composition tree?
0 reputation · 23 Aug 2024, 17:48 UTC
0 reputation · 23 Aug 2024, 17:48 UTC
In Compose, a composable can capture references in lambda parameters. When the composable is removed from the composition tree, the runtime does not expose a public mechanism to nullify these references, raising the possibility that objects referenced by the lambda remain reachable and cause a memory leak, especially in navigation scenarios where screens are frequently created and destroyed.
Current Compose releases (up to 1.5.x) provide no documented cleanup behavior for lambda captures, and the runtime does not expose an API to query retained composables. Developers must therefore rely on external profilers to detect leaks.
Given these constraints, the key open question is whether the Compose runtime will automatically clear references held by lambda captures when a composable exits the composition tree, and if not, what pattern should be used to guarantee timely cleanup.
Does the Compose runtime automatically nullify references captured in lambdas when a composable is removed from the composition tree? Which lifecycle integration pattern best ensures that ViewModel and lambda captures are released in complex navigation flows?
31775 reputation · 23 Aug 2024, 20:25 UTC
Jetpack Compose does not nullify or remove objects captured by a lambda when the composable that created the lambda leaves the composition tree.
rememberUpdatedState or pass stable parameters instead of capturing mutable state.DisposableEffect or LaunchedEffect with key‑change).To give a precise recommendation, please clarify: Where is the lambda being stored or retained after the composable leaves the tree?
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 24 Aug 2024, 04:46 UTC
Compose only drops a lambda when the composable that created it is pruned and no external reference keeps it alive. If the lambda is stored or passed to a ViewModel, coroutine, or static holder, it survives the composable’s lifecycle and can cause a leak. Wrap them in DisposableEffect to clear on dispose. For state that must survive recompositions, use rememberUpdatedState so the old capture is released when the composable exits.
When a screen is popped from the back‑stack, the ViewModel scoped to that graph may still hold the lambda. Call clear() in onCleared() or set the reference to null in a DisposableEffect to guarantee timely cleanup.