Я создаю приложение для Android с JetPack Compose с использованием BottomSheetScaffold, и я не уверен в лучшем подходе для управления состоянием листа. Должен ли я управлять им на композиционном уровне для прямого управления или делегировать его в ViewModel?
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(
navController: NavHostController,
scaffoldViewModel: ScaffoldViewModel,
) {
val sheetScaffoldState = rememberBottomSheetScaffoldState()
val scope = rememberCoroutineScope()
// Direct sheet control function
val expandSheet: (Boolean) -> Unit = { shouldExpand ->
scope.launch {
if (shouldExpand) {
sheetScaffoldState.bottomSheetState.expand()
} else {
sheetScaffoldState.bottomSheetState.partialExpand()
}
}
}
BottomSheetScaffold(
scaffoldState = sheetScaffoldState,
sheetContent = {
SheetContent(
onMinimize = { expandSheet(false) } // Direct call
)
},
sheetDragHandle = {
DragHandle(
onClick = { expandSheet(true) } // Direct call
)
}
) { paddingValues ->
MainContent(
onSearchClick = { destination ->
expandSheet(true) // Direct call
scaffoldViewModel.navigate(destination)
}
)
}
}
< /code>
Альтернативный подход (ViewModel делегирование) < /p>
// ViewModel
class ScaffoldViewModel : ViewModel() {
private val _sheetState = MutableStateFlow(SheetAction.None)
val sheetState = _sheetState.asStateFlow()
fun expandSheet() {
_sheetState.value = SheetAction.Expand
}
fun partialExpandSheet() {
_sheetState.value = SheetAction.PartialExpand
}
}
enum class SheetAction { None, Expand, PartialExpand }
// Composable
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(
navController: NavHostController,
scaffoldViewModel: ScaffoldViewModel,
) {
val sheetScaffoldState = rememberBottomSheetScaffoldState()
val scope = rememberCoroutineScope()
val sheetAction by scaffoldViewModel.sheetState.collectAsStateWithLifecycle()
// Handle ViewModel sheet actions
LaunchedEffect(sheetAction) {
when (sheetAction) {
SheetAction.Expand -> {
scope.launch { sheetScaffoldState.bottomSheetState.expand() }
}
SheetAction.PartialExpand -> {
scope.launch { sheetScaffoldState.bottomSheetState.partialExpand() }
}
SheetAction.None -> { /* Do nothing */ }
}
}
BottomSheetScaffold(
scaffoldState = sheetScaffoldState,
sheetContent = {
SheetContent(
onMinimize = scaffoldViewModel::partialExpandSheet // ViewModel call
)
},
sheetDragHandle = {
DragHandle(
onClick = scaffoldViewModel::expandSheet // ViewModel call
)
}
) { paddingValues ->
MainContent(
onSearchClick = { destination ->
scaffoldViewModel.expandSheet() // ViewModel call
scaffoldViewModel.navigate(destination)
}
)
}
}
В подходе ViewModel у нас есть дополнительные шаги (ViewModel → StateFlow → LaunchEefcect → лист)
Не нужно вызывать лист из других. Android/Compose Best Practices?
Я создаю приложение для Android с JetPack Compose с использованием BottomSheetScaffold, и я не уверен в лучшем подходе для управления состоянием листа. Должен ли я управлять им на композиционном уровне для прямого управления или делегировать его в ViewModel?[code]@OptIn(ExperimentalMaterial3Api::class) @Composable fun MainScreen( navController: NavHostController, scaffoldViewModel: ScaffoldViewModel, ) { val sheetScaffoldState = rememberBottomSheetScaffoldState() val scope = rememberCoroutineScope()
// Direct sheet control function val expandSheet: (Boolean) -> Unit = { shouldExpand -> scope.launch { if (shouldExpand) { sheetScaffoldState.bottomSheetState.expand() } else { sheetScaffoldState.bottomSheetState.partialExpand() } } }
fun expandSheet() { _sheetState.value = SheetAction.Expand }
fun partialExpandSheet() { _sheetState.value = SheetAction.PartialExpand } }
enum class SheetAction { None, Expand, PartialExpand }
// Composable @OptIn(ExperimentalMaterial3Api::class) @Composable fun MainScreen( navController: NavHostController, scaffoldViewModel: ScaffoldViewModel, ) { val sheetScaffoldState = rememberBottomSheetScaffoldState() val scope = rememberCoroutineScope() val sheetAction by scaffoldViewModel.sheetState.collectAsStateWithLifecycle()