如何在组合导航中处理类似于 onActivityResult 的行为?
How to handle behavior similar to onActivityResult in compose navigation?
我有一个设置,我想导航到结果的可组合项,然后根据该结果我想从父项启动另一个可组合项。
这是设置
ScreenA 为结果启动 Screen B(用户在 screenB 中做某事)-> ScreenB 设置结果并从堆栈中弹出自身-> ScreenA 查看结果并根据值启动 ScreenC。
这里的问题是,一旦 ScreenB 设置了结果,我在结果上设置的观察器就会无限发射。
这是我的设置的简化版本:
fun AppNavHost(
navController: NavHostController
) {
NavHost(
navController = navController,
startDestination = "ScreenA",
) {
composable("ScreenA") {
ScreenA(
onClick = {
navController.navigate("ScreenB")
}
)
val result = navController.currentBackStackEntry
?.savedStateHandle
?.getLiveData<String>("key")
?.observeAsState()
result?.value?.let { str ->
// This seems to not remove the key or at least
// the live data value is not nulled out
navController.currentBackStackEntry
?.savedStateHandle
?.remove<String>("key")
if (str == "result") {
// This condition hits infinitely
navController.navigate("ScreenC")
// This logs infinitely
Log.d("TAG", "found result: $str")
}
}
}
composable("ScreenB") {
ScreenB(
onClick = {
navController.previousBackStackEntry
?.savedStateHandle
?.set("key", "result")
navController.popBackStack()
}
)
}
composable("ScreenC") { ScreenC() }
}
}
我已经看过 并且我这里的设置是相似的。如何修复此行为,使 ScreenB 的结果只被读取一次?
使用 LaunchedEffect 避免在重新合成级别多次调用导航。
NavHost(
navController = navController,
startDestination = "ScreenA",
) {
composable("ScreenA") {
Button(
onClick = {
navController.navigate("ScreenB")
},
modifier = Modifier.padding(16.dp)
) {
Text("Go to Screen B")
}
val result = navController.currentBackStackEntry
?.savedStateHandle
?.getLiveData<String>("key")
?.observeAsState()
result?.value?.let { str ->
navController.currentBackStackEntry
?.savedStateHandle
?.remove<String>("key")
LaunchedEffect(str) {
if (str == "result") {
navController.navigate("ScreenC")
Log.d("TAG", "found result: $str")
}
}
}
}
composable("ScreenB") {
Button(
onClick = {
navController.previousBackStackEntry
?.savedStateHandle
?.set("key", "result")
navController.popBackStack()
}
) {
Text("Screen B")
}
}
composable("ScreenC") { ScreenC() }
}
我有一个设置,我想导航到结果的可组合项,然后根据该结果我想从父项启动另一个可组合项。 这是设置
ScreenA 为结果启动 Screen B(用户在 screenB 中做某事)-> ScreenB 设置结果并从堆栈中弹出自身-> ScreenA 查看结果并根据值启动 ScreenC。
这里的问题是,一旦 ScreenB 设置了结果,我在结果上设置的观察器就会无限发射。
这是我的设置的简化版本:
fun AppNavHost(
navController: NavHostController
) {
NavHost(
navController = navController,
startDestination = "ScreenA",
) {
composable("ScreenA") {
ScreenA(
onClick = {
navController.navigate("ScreenB")
}
)
val result = navController.currentBackStackEntry
?.savedStateHandle
?.getLiveData<String>("key")
?.observeAsState()
result?.value?.let { str ->
// This seems to not remove the key or at least
// the live data value is not nulled out
navController.currentBackStackEntry
?.savedStateHandle
?.remove<String>("key")
if (str == "result") {
// This condition hits infinitely
navController.navigate("ScreenC")
// This logs infinitely
Log.d("TAG", "found result: $str")
}
}
}
composable("ScreenB") {
ScreenB(
onClick = {
navController.previousBackStackEntry
?.savedStateHandle
?.set("key", "result")
navController.popBackStack()
}
)
}
composable("ScreenC") { ScreenC() }
}
}
我已经看过
使用 LaunchedEffect 避免在重新合成级别多次调用导航。
NavHost(
navController = navController,
startDestination = "ScreenA",
) {
composable("ScreenA") {
Button(
onClick = {
navController.navigate("ScreenB")
},
modifier = Modifier.padding(16.dp)
) {
Text("Go to Screen B")
}
val result = navController.currentBackStackEntry
?.savedStateHandle
?.getLiveData<String>("key")
?.observeAsState()
result?.value?.let { str ->
navController.currentBackStackEntry
?.savedStateHandle
?.remove<String>("key")
LaunchedEffect(str) {
if (str == "result") {
navController.navigate("ScreenC")
Log.d("TAG", "found result: $str")
}
}
}
}
composable("ScreenB") {
Button(
onClick = {
navController.previousBackStackEntry
?.savedStateHandle
?.set("key", "result")
navController.popBackStack()
}
) {
Text("Screen B")
}
}
composable("ScreenC") { ScreenC() }
}