处理全局 Compose 中的 Snackbar 显示

问题描述 投票:0回答:1

嗨,我正在使用下面的代码来处理全局的小吃栏显示。我是作曲新手,我浏览了各种视频和博客,最后想出了以下内容。这是正确的做事方式吗?

我正在MainActivity中处理snackbar的渲染,如下所示

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            SunnyTheme {
                val snackBarHostState = remember { SnackbarHostState() }
                val coroutineScope = rememberCoroutineScope()

                Scaffold(
                    snackbarHost = { SnackbarHost(snackBarHostState) },
                ) {
                    Box(modifier = Modifier.padding(it)) {

                        val showSnackBar: (
                            message: String?,
                            actionLabel: String,
                            actionPerformed: () -> Unit,
                            dismissed: () -> Unit
                        ) -> Unit = { message, actionLabel, actionPerformed, dismissed ->

                            coroutineScope.launch {
                                val result =
                                    message?.let {
                                        snackBarHostState.showSnackbar(
                                            message = it,
                                            actionLabel = actionLabel,
                                        )
                                    }
                                when (result) {
                                    ActionPerformed -> {
                                        actionPerformed.invoke()
                                    }
                                    Dismissed -> {
                                        dismissed.invoke()
                                    }
                                    else -> {
                                        Timber.e("WTf.......$#$%")
                                    }
                                }
                            }
                        }
                        SunnyApp(showSnackBar)
                    }
                }
            }
        }
    }


}

@Composable
fun SunnyApp(
    showSnackBar: (
        message: String?,
        actionLabel: String,
        actionPerformed: () -> Unit,
        dismissed: () -> Unit
    ) -> Unit,
) {
    val navController = rememberNavController()
    SetupNavGraph(navHostController = navController, showSnackBar = showSnackBar)
}

下面是我的导航图:

@Composable
fun SetupNavGraph(
    navHostController: NavHostController,
    showSnackBar: (
        message: String?,
        actionLabel: String,
        actionPerformed: () -> Unit,
        dismissed: () -> Unit
    ) -> Unit,
) {
    NavHost(
        navController = navHostController,
        startDestination = Screen.Splash.route,
    ) {
        composable(route = Screen.Splash.route) {
            SplashScreen {
                navHostController.popBackStack()
                navHostController.navigate(Screen.Home.route)
            }
        }

        composable(route = Screen.Home.route) {
            HomeScreen(
                showSnackBar = showSnackBar,
                navigateToSelectLocationScreen = { navHostController.navigate(Screen.SelectLocation.route) },
            )
        }

        composable(route = Screen.SelectLocation.route) {
            SelectLocationScreen()
        }
    }
}

这就是我从主屏幕上调用它的方式。在

NetworkResult.Exception

@Composable
fun HomeScreen(
    homeViewModel: HomeViewModel = hiltViewModel(),
    showSnackBar: (
        message: String?,
        actionLabel: String,
        actionPerformed: () -> Unit,
        dismissed: () -> Unit
    ) -> Unit,
    navigateToSelectLocationScreen: () -> Unit,
) {
    val homeUiState by homeViewModel.uiState.collectAsStateWithLifecycle()
    val context = LocalContext.current

    if (homeUiState.lat == 0.0) {
        LoadingUi()

        LocationPermissionUI(
            context = context,
            permissionCallback = { permissionAction ->
                when (permissionAction) {
                    is PermissionAction.OnPermissionGranted -> {
                        Timber.e("Location permission granted")

                        getUserCurrentLocation(context, permissionAction.precise) {
                            Timber.e("Lat : ${it.result.latitude}")
                            Timber.e("Lng : ${it.result.longitude}")

                            homeViewModel.setLocation(it.result.latitude, it.result.longitude)
                        }
                    }

                    is PermissionAction.OnPermissionDenied -> {
                        Timber.e("Location permission denied")
                    }
                }
            },
        )
    } else {
        when (homeUiState.networkResult) {
            is NetworkResult.Loading -> {
                LoadingUi()
            }

            is NetworkResult.Success -> {
                
            }

            is NetworkResult.Error -> {
               
            }

            is NetworkResult.Exception -> {
                var exceptionMessage =
                    (homeUiState.networkResult as NetworkResult.Exception).throwable.localizedMessage
                Timber.e("Exception message: $exceptionMessage")
                showSnackBar.invoke(
                    exceptionMessage,
                    "Retry",
                    {
                        homeViewModel.setLocation(homeUiState.lat, homeUiState.lon)
                    },
                    {
                        //do nothing
                    }
                )

            }
        }
    }
}
android kotlin android-jetpack-compose android-snackbar
1个回答
0
投票

在我的项目中我也遇到过类似的情况。我解决这个问题的方法是创建一个 LocalSnackbarState 值,然后通过我的组合树传递该值。我建议阅读https://developer.android.com/jetpack/compose/compositionlocal

© www.soinside.com 2019 - 2024. All rights reserved.