Modo docs Help

Screen Effects

Here’s the improved version of your documentation text:

Modo provides a set of side effects that are similar to the LaunchedEffect and DisposableEffect from Jetpack Compose, but they are tied to the screen lifecycle:

  • LaunchedScreenEffect - Executes the given block: suspend CoroutineScope.() -> Unit when the screen is created and cancels the coroutine scope when the screen is removed.

  • DisposableScreenEffect - Executes the given effect: DisposableEffectScope.() -> DisposableEffectResult when the screen is created and calls the DisposableEffectResult.dispose() of the returned DisposableEffectResult when the screen is removed.

  • OnScreenRemoved - Executes when the screen is removed from the navigation graph. It is similar to the DisposableScreenEffect.

  • LifecycleScreenEffect - A shortcut for subscribing to a screen's lifecycle, using DisposableScreenEffect under the hood.

You can use these effects when you need to perform an action when the screen is created and then dispose of it when the screen is removed. For example, you can use it to create and close a DI scope.

  1. Effects are called once per Screen instance, when the given function enters the composition and this block hasn't been called for this Screen instance.

  2. The effect is disposed of when the Screen is removed from the navigation graph.

Examples of Usage

Analytics

You can use DisposableScreenEffect to track screen creation and removal events:

DisposableScreenEffect { logcat { "Analytics: screen created. Counter: $counter." } onDispose { logcat { "Analytics: screen destroyed. Counter: $counter." } } }

DI Scope Integration

You can use OnScreenRemoved with remember to create and close a DI scope. The scope of a Screen can be identified by screenKey. Here is a sample of how you can use it with Toothpick:

@Composable internal fun Screen.rememberScreenScope( parentScope: Scope = LocalToothpickScope.current, moduleProvider: () -> Module = { module { } }, ): Scope { val scope = remember { getOrInitScope(screenKey, parentScope, moduleProvider) } OnScreenRemoved("scope") { Toothpick.closeScope(scope.name) } return scope } private fun getOrInitScope( screenKey: ScreenKey, parentScope: Scope, moduleProvider: () -> Module = { module { } }, ): Scope { val scopeName = screenKey.scopeName() return if (Toothpick.isScopeOpen(scopeName)) { Toothpick.openScope(scopeName) } else { val scope = Toothpick.openScopes(parentScope.name, scopeName) scope.installModules(moduleProvider.invoke()) } }
Last modified: 12 June 2024