7

Jetpack Compose Effect Handlers

 2 years ago
source link: https://effectiveandroid.substack.com/p/jetpack-compose-effect-handlers
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd4f6bf-ee5b-4cdf-b6ce-c05bcdf712fc_2850x1900.jpeg

What is a side effect?

A side effect is Anything that escapes the scope of the function where it is called. Here is an effect to keep some external state updated:

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F701fa132-e857-4824-a9a8-cf5394a5cbc4_1288x640.png

It initializes and updates a callback reference on an external object as a side effect of the composition. We don’t have control over when the effect runs (Composable functions can run multiple times), and it is never disposed.

We need to ensure that

  • Effects run on the correct lifecycle step

  • Effects can dispose resources when leaving composition

  • Suspend effects are cancelled when leaving composition

  • Effects that depend on an input that varies over time are automatically disposed/cancelled & relaunched every time it varies

These mechanisms are provided by the Effect Handlers.

Effect Handlers

Composables enter the composition when attached and leave it when detached. Between both events, effects run. Some effects can outlive this cycle and span across recompositions.

DisposableEffect

For an effect that requires cleanup before leaving.

  • Fired when entering and every time keys change

  • Disposed when leaving, and every time keys change (before re-trigger)

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F1f26f68e-d115-4815-91be-c9d2c17fff0b_1766x1180.png

This handler attaches a callback to an external dispatcher when entering and disposes it when leaving. The dispatcher is used as a key to ensure dispose+restart if it changes. For spanning the same effect across recompositions instead of retriggering it you can pass a constant key: DisposableEffect(true) or DisposableEffect(Unit). DisposableEffectalways requires at least 1 key.

SideEffect

“Fire on this composition or forget”. If the composition fails, it gets discarded. Used for notifying state updates to objects not managed by Compose.

  • For effects that do not require dispose

  • Runs after every successful composition/recomposition

  • Publishing updates to external states not managed by Compose

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F1e75321f-e68f-4a9b-9097-c57ae0de8554_1318x798.png

currentRecomposeScope

Not an effect handler, but interesting. Same than View invalidate. Can be used from any Composable function to invalidate the composition locally 👉 enforce recomposition.

⚠️ Anti-pattern. Rely on Snapshot state to drive recomposition.

Can be useful when using a source of truth that is not compose State. This presenter does not rely on Compose State, invalidation is done manually:

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F4e3642c9-be9d-427e-86b5-40d838be7d01_1782x798.png

derivedStateOf

To derive some state from other state objects.

  • Useful when we have some mutable state and other states that need to be recalculated only when the original changes

  • An optimization: Avoids recalculating on every recomposition

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe1c4a38-56af-4215-9023-a1b6744d99d0_1868x1180.png
Example extracted from the official docs.

rememberCoroutineScope

To create jobs that are considered children of the composition.

  • Runs suspended effects bound to the composition lifecycle

  • Scope cancelled when leaving the composition

  • Same scope across recompositions: all submited jobs cancelled when leaving

  • Useful to launch jobs in response to user interactions

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F56dec943-9d3e-4d93-82df-fb4a3adfef07_1454x1266.png

Throttling on UI. Alike postDelayed for Views. Every time the input changes it cancels the previous job and posts a new one with a delay.

LaunchedEffect

Similar but for loading initial state when entering the composition instead of after user interaction.

  • Runs suspend effect when entering, cancels it when leaving

  • Cancels and relaunches the effect when key/s change/s

  • Also useful to span a job across recompositions

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7c4adf1-a971-4eea-a7d9-86bdfd19bb70_1558x754.png

produceState

Syntax sugar on top of LaunchedEffect. When LaunchedEffect feeds a State.

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9e68aa1-4cbd-4cdb-862d-288da724182c_1610x712.png

Supports default value. Behaves the same as LaunchedEffect.

rememberUpdatedState

To capture a value in an effect & update it later without triggering it.

  • Useful for long lived operations that would be costly to recreate and restart

  • Useful when effect depends on a value that might change over time but we still want the effect to span across recompositions

https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa861557-785e-4f38-b347-0445a7b40091_1438x1052.png
Example extracted from the official docs.

Every time it is called it will update its value but will not retrigger effects reading from it.

3rd party library adapters

There are adapters for multiple well known libraries that delegate to the effect handlers.

You can find documentation for all the adapters available to convert 3rd party data types to Compose State here. There is also a collectAsStateWithLifecycle variant for collecting flows safely in Android. Finally, there is an adapter to convert from Compose Snapshot State to a cold Flow here.

All these adapters rely on effect handlers like DisposableEffect, LaunchedEffect or produceState to observe new values emitted from the original source and map them into a Compose State instance.

Consider becoming a free or paid subscriber.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK