# PredictiveBackHandler

## Functions summary

|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/Composable https://developer.android.com/reference/kotlin/androidx/activity/compose/PredictiveBackHandler.composable#PredictiveBackHandler(kotlin.Boolean,kotlin.coroutines.SuspendFunction1)( enabled: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html, onBack: suspend (progress: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html<https://developer.android.com/reference/kotlin/androidx/activity/BackEventCompat>) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` An effect for handling predictive system back gestures. |

## Functions

### PredictiveBackHandler

Artifact: [androidx.activity:activity-compose](https://developer.android.com/jetpack/androidx/releases/activity) [View Source](https://cs.android.com/search?q=file:androidx/activity/compose/PredictiveBackHandler.kt+function:PredictiveBackHandler)

```
@Composable
fun PredictiveBackHandler(
    enabled: Boolean = true,
    onBack: suspend (progress: Flow<BackEventCompat>) -> Unit
): Unit
```

An effect for handling predictive system back gestures.

This effect registers a callback to receive updates on the progress of system back gestures as a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html` of `https://developer.android.com/reference/kotlin/androidx/activity/BackEventCompat`.

The `https://developer.android.com/reference/kotlin/androidx/activity/compose/package-summary#PredictiveBackHandler(kotlin.Boolean,kotlin.coroutines.SuspendFunction1)` lambda should be structured to handle the start, progress, completion, and cancellation of the gesture:

```kotlin
PredictiveBackHandler { progress: Flow<BackEventCompat> ->
  // This block is executed when the back gesture begins.
    try {
      progress.collect { backEvent ->
        // Handle gesture progress updates here.
      }
      // This block is executed if the gesture completes successfully.
    } catch (e: CancellationException) {
      // This block is executed if the gesture is cancelled.
      throw e
    } finally {
      // This block is executed either the gesture is completed or cancelled.
  }
}
```

The handler is registered once and stays attached for the lifetime of the `https://developer.android.com/reference/kotlin/androidx/lifecycle/LifecycleOwner`. Its `https://developer.android.com/reference/kotlin/androidx/activity/OnBackPressedCallback#isEnabled()` state automatically follows the lifecycle: it becomes enabled when the lifecycle is at least `https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle.State#STARTED` and disabled otherwise.

## Precedence

If multiple `https://developer.android.com/reference/kotlin/androidx/activity/compose/PredictiveBackHandler.composable#PredictiveBackHandler(kotlin.Boolean,kotlin.coroutines.SuspendFunction1)` are present in the composition, the one that is composed **last** among all enabled handlers will be invoked.

## Usage

It is important to call this composable **unconditionally** . Use the `enabled` parameter to control whether the handler is active. This is preferable to conditionally calling `https://developer.android.com/reference/kotlin/androidx/activity/compose/PredictiveBackHandler.composable#PredictiveBackHandler(kotlin.Boolean,kotlin.coroutines.SuspendFunction1)` (e.g., inside an `if` block), as conditional calls can change the order of composition, leading to unpredictable behavior where different handlers are invoked after recomposition.

## Timing Consideration

There are cases where a predictive back gesture may be dispatched within a rendering frame before the `https://developer.android.com/reference/kotlin/androidx/activity/compose/package-summary#PredictiveBackHandler(kotlin.Boolean,kotlin.coroutines.SuspendFunction1)` flag is updated, which can cause unexpected behavior (see [b/375343407](https://issuetracker.google.com/375343407), [b/384186542](https://issuetracker.google.com/384186542)). For example, if `enabled` is set to `false`, a gesture initiated in the same frame may still trigger this handler because the system sees the stale `true` value.

## Legacy Behavior

To restore the legacy add/remove behavior, set `https://developer.android.com/reference/kotlin/androidx/activity/ActivityFlags#isOnBackPressedLifecycleOrderMaintained()` to `false`. In legacy mode, the handler is added on `https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle.Event#ON_START` and removed on `https://developer.android.com/reference/kotlin/androidx/lifecycle/Lifecycle.Event#ON_STOP`, which may change dispatch ordering across lifecycle transitions.

```kotlin
import androidx.activity.BackEventCompat
import androidx.activity.compose.BackHandler
import androidx.activity.compose.PredictiveBackHandler
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var text by remember { mutableStateOf("") }

TextField(value = text, onValueChange = { text = it })

PredictiveBackHandler(text.isNotEmpty()) { progress: Flow<BackEventCompat> ->
    callback.preparePop()
    try {
        progress.collect { backEvent -> callback.updateProgress(backEvent.progress) }
        callback.popBackStack()
    } catch (e: CancellationException) {
        callback.cancelPop()
    }
}
```

| Parameters |
|---|---|
| `enabled: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = true` | Controls whether this handler is active. **Important** : Due to the timing issue described above, a gesture starting immediately after `enabled` is set to `false` may still trigger this handler. |
| `onBack: suspend (progress: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/index.html<https://developer.android.com/reference/kotlin/androidx/activity/BackEventCompat>) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | The suspending lambda to be invoked by the back gesture. It receives a `Flow` that can be collected to track the gesture's progress. |