嗨,我正在使用下面的代码来处理全局的小吃栏显示。我是作曲新手,我浏览了各种视频和博客,最后想出了以下内容。这是正确的做事方式吗?
我正在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
}
)
}
}
}
}
在我的项目中我也遇到过类似的情况。我解决这个问题的方法是创建一个 LocalSnackbarState 值,然后通过我的组合树传递该值。我建议阅读https://developer.android.com/jetpack/compose/compositionlocal