Jetpack Compose 导航结果

Jetpack Compose navigate for result

我在 Compose 版本中使用 Jetpack Navigation 库。我正在设置导航,如图所示 here

我希望能够从屏幕 A 导航到屏幕 B。一旦 B 执行某些操作并弹出返回堆栈,它将 return 屏幕 A 可以访问的结果。

我找到了一种使用 Activities 来执行此操作的方法,但我想避免创建任何额外的 Activity 并在 compose 中执行此操作。

从您想要 return 数据的可组合项中,您可以执行以下操作:

navController.previousBackStackEntry
    ?.savedStateHandle
    ?.set("your_key", "your_value")
navController.popBackStack()

然后,您可以使用 LiveData.

从源 Composable 中监听更改
val secondScreenResult = navController.currentBackStackEntry
    ?.savedStateHandle
    ?.getLiveData<String>("your_key")?.observeAsState()
...
secondScreenResult?.value?.let {
    // Read the result
}
val navController = rememberNavController()
composable("A") {
    val viewmodel: AViewModel = hiltViewModel()
    AScreen()
}
composable("B") {
    val viewmodel: BViewModel = hiltViewModel()
    val previousViewmodel: AViewModel? = navController
        .previousBackStackEntry?.let {
            hiltViewModel(it)
        }
    BScreen(
       back = { navController.navigateUp() },
       backWhitResult = { arg ->
           previousViewmodel?.something(arg)
       }
    )
}

如果您只需要一次获取值,则需要在使用后删除值:

val screenResultState = navController.currentBackStackEntry
    ?.savedStateHandle
    ?.getLiveData<String>("some_key")?.observeAsState()

screenResultState?.value?.let {
    ...
    // make something, for example `viewModel.onResult(it)`
    ...
    //removing used value
    navController.currentBackStackEntry
        ?.savedStateHandle
        ?.remove<String>("some_key")
}

我也在函数中提取了它(对于 JetPack Compose)

@Composable
fun <T> NavController.GetOnceResult(keyResult: String, onResult: (T) -> Unit){
    val valueScreenResult =  currentBackStackEntry
        ?.savedStateHandle
        ?.getLiveData<T>(keyResult)?.observeAsState()

    valueScreenResult?.value?.let {
        onResult(it)
       
        currentBackStackEntry
            ?.savedStateHandle
            ?.remove<T>(keyResult)
    }
}

您可以将其复制到您的项目中并像这样使用:

navController.GetOnceResult<String>("some_key"){
    ...
    // make something
}