Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Windows Tipps & SecurityGoogles neues Betriebssystem ist da – heißt jetzt aber komplett anders(22.09.2026 um 12:08 Uhr)
Windows Tipps & SecurityGooglebook-Premiere: Alle 5 Modelle ausprobiert – zwei stechen heraus(22.09.2026 um 12:30 Uhr)
Sichere ProgrammierungDeprecation notice: All-platform CodeQL bundle(22.09.2026 um 11:21 Uhr)
Sichere ProgrammierungCodeSOD: The John Cage Variable(22.09.2026 um 08:30 Uhr)
Windows Tipps & SecurityGoogles neues Betriebssystem ist da – heißt jetzt aber komplett anders(22.09.2026 um 12:08 Uhr)
Windows Tipps & SecurityGooglebook-Premiere: Alle 5 Modelle ausprobiert – zwei stechen heraus(22.09.2026 um 12:30 Uhr)
Sichere ProgrammierungDeprecation notice: All-platform CodeQL bundle(22.09.2026 um 11:21 Uhr)
Sichere ProgrammierungCodeSOD: The John Cage Variable(22.09.2026 um 08:30 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Navigate back with results in Jetpack Compose Navigation

If you’ve ever needed to open a screen, let the user pick something, and then pass that selection back to the previous screen, you probably reached for shared ViewModels, singletons, or brittle route parameters. There’s a simpler way that …

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Navigate back with results in Jetpack Compose Navigation



If you’ve ever needed to open a screen, let the user pick something, and then pass that selection back to the previous screen, you probably reached for shared ViewModels, singletons, or brittle route parameters.



There’s a simpler way that works with Jetpack Compose Navigation: navigate forward → wait for a result → navigate back with that result.



This post introduces a tiny helper you can drop into your project and explains how it works, complete with examples, pitfalls, and testing tips.






The Helper



Put this file somewhere in your project as-is.




import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.navigation.NavController
import kotlin.coroutines.resume
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.json.Json

private const val RESULT_KEY = "result"

fun <T> NavController.navigateBackWithResult(value: T) {
previousBackStackEntry?.savedStateHandle?.set(RESULT_KEY, value)
navigateUp()
}

inline fun <reified T> NavController.navigateBackWithSerializableResult(value: T) {
navigateBackWithResult(Json.encodeToString(value))
}

suspend fun <T> NavController.navigateForResult(route: Any): T? =
suspendCancellableCoroutine { continuation ->
val currentNavEntry = currentBackStackEntry
?: throw IllegalStateException("No current back stack entry found")

navigate(route)

val lifecycleObserver = object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_START) {
continuation.resume(currentNavEntry.savedStateHandle[RESULT_KEY])
currentNavEntry.savedStateHandle.remove<T>(RESULT_KEY)
currentNavEntry.lifecycle.removeObserver(this)
}
}
}

currentNavEntry.lifecycle.addObserver(lifecycleObserver)

continuation.invokeOnCancellation {
currentNavEntry.savedStateHandle.remove<T>(RESULT_KEY)
currentNavEntry.lifecycle.removeObserver(lifecycleObserver)
}
}

suspend inline fun <reified T> NavController.navigateForSerializableResult(route: Any): T? {
val result: String = navigateForResult(route) ?: return null
return Json.decodeFromString(result)
}







NavigateBackWithResult.kt






How it works





  1. Caller launches a route with navigateForResult(route).
    The current entry is remembered, navigation occurs, and a lifecycle observer is set up.


  2. Callee finishes by calling navigateBackWithResult(value).
    The result is stored in the caller’s SavedStateHandle under a fixed key.


  3. Caller resumes on ON_START.
    The coroutine unblocks, retrieves the result, and clears the key to avoid stale values.



This is lifecycle-aware, type-safe, and minimal - no ActivityResultContract, no shared ViewModel, no event bus.






How to use it



Here's a simple example to see the pattern in action. Imagine a screen where the user picks a color, and when they go back, the chosen value is passed to the previous screen. This is the most straightforward case: a basic type (String) being sent back.




// Routes:

object Routes {
const val HOME = "home"
const val COLOR_PICKER = "color-picker"
}

// Nav host:

@Composable
fun AppNavHost(navController: NavHostController = rememberNavController()) {
NavHost(navController, startDestination = Routes.HOME) {
composable(Routes.HOME) { HomeScreen(navController) }
composable(Routes.COLOR_PICKER) { ColorPickerScreen(navController) }
}
}

// Caller (HomeScreen):

@Composable
fun HomeScreen(navController: NavController) {
val scope = rememberCoroutineScope()
var selectedColor by remember { mutableStateOf<String?>(null) }

Column(Modifier.padding(16.dp)) {
Text("Selected: ${'$'}{selectedColor ?: "none"}")
Button(onClick = {
scope.launch {
val result: String? = navController.navigateForResult(Routes.COLOR_PICKER)
selectedColor = result
}
}) {
Text("Pick color")
}
}
}

// Callee (ColorPickerScreen):

@Composable
fun ColorPickerScreen(navController: NavController) {
val colors = listOf("Red", "Green", "Blue")
Column(Modifier.padding(16.dp)) {
colors.forEach { color ->
Button(onClick = { navController.navigateBackWithResult(color) }) {
Text(color)
}
}
OutlinedButton(onClick = { navController.navigateUp() }) {
Text("Cancel")
}
}
}










Edge cases and gotchas



There are a few edge cases and nuances worth keeping in mind. Results are always nullable (T?), so you should be prepared to handle the case where the user cancels or navigates back without setting anything. If you use the non-serializable variant and the caller and callee don’t agree on the type, you’ll hit a ClassCastException, so type alignment is critical. Results also don’t survive process death, since this mechanism is essentially a callback rather than persistent state. Finally, avoid waiting for multiple results concurrently from the same destination; if you need that, wrap access in your own guard or queue to prevent conflicts.






Conclusion



This helper gives you a lightweight, lifecycle-aware pattern for passing data back through the Compose Navigation stack: you simply drop it into your project, call navigateForResult() when moving forward, and then call navigateBackWithResult() when returning. That’s all it takes - no extra contracts and no brittle hacks.



Happy coding!

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Navigate back with results in Jetpack Compose Navigation

Thematisch verwandte Begriffe: Navigate, back, with, results · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94493 | A vulnerability was detected in Gigatech PDV5701 1.0.31_240305_112640. T…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick