Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import androidx.navigation3.runtime.result.rememberResultEventBus
import androidx.navigation3.runtime.result.rememberResultEventBusNavEntryDecorator
import com.example.compose.snippets.navigation3.savingstate.Home
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -62,3 +64,24 @@ fun DecoratorsBasic() {
)
// [END android_compose_navigation3_decorator_2]
}

@Composable
fun DecoratorsResultEventBus() {
// [START android_compose_navigation3_decorator_result_hoist]
val resultEventBus = rememberResultEventBus()

NavDisplay(
/* ... */
// [START_EXCLUDE silent]
backStack = rememberNavBackStack(Home),
entryProvider = entryProvider<NavKey> {
entry<Home> { Text("Welcome to Nav3") }
},
// [END_EXCLUDE]
entryDecorators = listOf(
rememberSaveableStateHolderNavEntryDecorator(),
rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
)
)
// [END android_compose_navigation3_decorator_result_hoist]
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ package com.example.compose.snippets.navigation3.migration

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.StateFlow
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.result.LocalResultEventBus
import androidx.navigation3.runtime.result.ResultEffect
import androidx.navigation3.scene.DialogSceneStrategy
import androidx.navigation3.ui.NavDisplay
import android.content.Intent
Expand All @@ -36,6 +39,7 @@ import androidx.navigation3.runtime.deeplink.DeepLinkRequest
import androidx.navigation3.runtime.deeplink.DeepLinkUri
import androidx.navigation3.runtime.deeplink.UriDeepLinkMatcher
import androidx.navigation3.runtime.deeplink.invoke
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable
import kotlinx.serialization.serializer

Expand Down Expand Up @@ -152,6 +156,44 @@ private object SnippetLifecycleAfter {
}
}

private object SnippetResultAfter {
@Serializable data object ContactPickerRoute : NavKey
data class Contact(val name: String = "")
class ComposeMessageViewModel : ViewModel() {
val recipient: Contact? = null
fun onRecipientSelected(contact: Contact) {}
}

@Composable private fun ContactPickerScreen(onContactSelected: (Contact) -> Unit) {}
@Composable private fun ComposeMessageContent(recipient: Contact?) {}

fun EntryProviderScope<NavKey>.entryProviderResult(navigator: Navigator) {
// [START android_compose_navigation3_result_after]
// Sender destination (in entryProvider):
entry<ContactPickerRoute> {
val resultBus = LocalResultEventBus.current

ContactPickerScreen(
onContactSelected = { contact ->
resultBus.sendResult<Contact>(result = contact)
navigator.goBack()
}
)
}

// Receiver destination:
@Composable
fun ComposeMessageScreen(viewModel: ComposeMessageViewModel = viewModel()) {
ResultEffect<Contact> { contact ->
viewModel.onRecipientSelected(contact)
}

ComposeMessageContent(recipient = viewModel.recipient)
}
// [END android_compose_navigation3_result_after]
}
}

private object SnippetDeepLinksAfter {
@Serializable data class RouteA(val id: String) : NavKey
@Serializable data object HomeKey : NavKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,25 @@ package com.example.compose.snippets.navigation3.migration

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import kotlinx.coroutines.flow.StateFlow
import androidx.navigation.NavHostController
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.dialog
import androidx.navigation.compose.navigation
import androidx.navigation.navDeepLink
import androidx.navigation.toRoute
import kotlinx.serialization.Serializable
import kotlin.reflect.KClass
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable

// Dummy screens for compilation
@Composable private fun ScreenA(title: String) {}
Expand Down Expand Up @@ -126,6 +128,34 @@ private object SnippetLifecycleBefore {
}
}

private object SnippetResultBefore {
data class Contact(val name: String = "")
class ComposeMessageViewModel : ViewModel() {
fun onRecipientSelected(contact: Contact) {}
}

@Composable
fun ResultBeforeSnippet(
navController: NavController,
contact: Contact,
viewModel: ComposeMessageViewModel
) {
// [START android_compose_navigation3_result_before]
// Sender destination:
navController.previousBackStackEntry?.savedStateHandle?.set("contact_key", contact)
navController.popBackStack()

// Receiver destination:
val lifecycleOwner = LocalLifecycleOwner.current
navController.currentBackStackEntry?.savedStateHandle
?.getLiveData<Contact>("contact_key")
?.observe(lifecycleOwner) { contact ->
viewModel.onRecipientSelected(contact)
}
// [END android_compose_navigation3_result_before]
}
}

private object SnippetDeepLinksBefore {
@Serializable data class RouteA(val id: String)

Expand Down
Loading
Loading