android Jetpack编写导航结果被多次触发(即使使用`savedStateHandle?.remove< T>(key)

nwlls2ji  于 2023-06-04  发布在  Android
关注(0)|答案(1)|浏览(227)

我的应用程序中有两个屏幕:屏幕A和屏幕B
SCREEN_A ->监听SCREEN_B的结果

@Composable
fun ScreenA() {
    val result =  currentBackStackEntry
        ?.savedStateHandle
        ?.getLiveData<String>("resultKey")
        ?.observeAsState()

    result?.value?.let {
        Log.d("AABBCCDDEE", "TESTING RESULT")

        currentBackStackEntry
            ?.savedStateHandle
            ?.remove<String>("resultKey")
    }

    // ...
}

SCREEN_B ->触发一个结果并从堆栈中弹出自身

@Composable
fun ScreenB() {
    val coroutineScope = rememberCoroutineScope()

    LaunchedEffect(key1 = Unit) {
        scope.launch {
            delay(3000)
            navController.previousBackStackEntry
                ?.savedStateHandle
                ?.set("resultKey", "TESTING HERE : )")
            navController.popBackStack()
        }
    }
}

问题是,当应用程序从SCREEN_B导航回SCREEN_A时,结果被触发两次(字符串“TESTING RESULT”被打印两次)。
我能做些什么来避免这种情况?
我以为这段代码就足够了

currentBackStackEntry
    ?.savedStateHandle
    ?.remove<String>("resultKey")
2izufjch

2izufjch1#

最好使用LaunchedEffect对结果数据进行getStateFlow处理,LaunchedEffect更适合Composables。
例如,您可以为NavController创建扩展,以封装逻辑

@Composable
fun <T> NavController.CollectDataResult(key: String, initialValue: T, result: (T) -> Unit) {
    val resultState = currentBackStackEntry?.savedStateHandle
        ?.getStateFlow(key, initialValue)?.collectAsState()

    LaunchedEffect(resultState) {
        resultState?.value?.let {
            result(it)
            currentBackStackEntry?.savedStateHandle?.remove<T>(key)
        }
    }
}

相关问题