簡體   English   中英

Jetpack Compose 導航結果

[英]Jetpack Compose navigate for result

我在 Compose 版本中使用 Jetpack Navigation 庫。 我正在設置導航,就像這里顯示的那樣

我希望能夠從屏幕 A 導航到屏幕 B。一旦 B 執行某些操作並彈出返回堆棧,它將返回屏幕 A 可以訪問的結果。

我找到了一種使用 Activities here來執行此操作的方法,但我想避免創建任何額外的 Activity 並在 compose 中執行此操作。

從要返回數據的 Composable 中,您可以執行以下操作:

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

然后,從源 Composable 中,您可以使用LiveData監聽更改。

val secondScreenResult = navController.currentBackStackEntry
    ?.savedStateHandle
    ?.getLiveData<String>("your_key")?.observeAsState()
...
secondScreenResult?.value?.let {
    // Read the result
}

如果您只需要一次獲取值,則需要在使用后刪除值:

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")
}

我還在 function 中提取它(用於 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
}

對於 jetpack compose,您必須將FlowcollectAsState一起使用以獲得結果:

navController.currentBackStackEntry
?.savedStateHandle?.getStateFlow<Boolean?>("refresh", false)
?.collectAsState()?.value?.let {
if (it)screenVM.refresh() }

你也可以在screenVM.refresh()之后添加這個來刪除條目:

 navController.currentBackStackEntry
                ?.savedStateHandle ?.set("refresh", false)

您可以在沒有 LiveData 或 Flow 的情況下獲得結果,您可以使用savedStateHandle.remove方法。 我認為這是更簡單的方法:

val secondResult = appNavController.currentBackStackEntry?.savedStateHandle?.remove<Data?>("data")
secondResult?.let { data ->
    Log.d(TAG, "Data result: $data")
}

添加依賴

implementation "androidx.compose.runtime:runtime-livedata:$compose_version"

在發件人屏幕上設置一個鍵值對發送回調用者屏幕,我使用 Boolean 鍵名稱為“key”值 true

navController.previousBackStackEntry?.savedStateHandle?.set("key", true)

向上導航

navController.navigateUp()

接收者屏幕(調用者)聽取結果,然后將其刪除:

 val result =  navController.currentBackStackEntry?.savedStateHandle
    ?.getLiveData<Boolean>("key")?.observeAsState()
result?.value?.let {
    navController.currentBackStackEntry?.savedStateHandle
        ?.remove<Boolean>("key")
}

第一屏

@Composable fun FirstScreen(navController: NavController){

val result =  navController.currentBackStackEntry?.savedStateHandle
    ?.getLiveData<Boolean>("key")?.observeAsState()
result?.value?.let {
    navController.currentBackStackEntry?.savedStateHandle
        ?.remove<Boolean>("key")
}

Button(onClick = {
    navController.navigateUp("secondScreen")
}) {
    "Open second screen"
}}
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)
       }
    )
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM