Я создал приложение для Android с использованием Kotlin + Room + Hilt + MVVM и т. д. Я создал экран, на котором могу создавать или редактировать игроков, для этого я создал составные элементы, модель представления и запечатанный класс, представляющий UiState.
Он работает нормально, но у меня есть две переменные (имя и псевдоним) с RememberSaveable в составной части, которая, я думаю, должна быть в модели представления или интегрирована в UiState. Можете ли вы мне помочь с этим? В порядке ли мой код или мне следует улучшить его после перемещения MVVM этих переменных? Какова наилучшая практика?
Это код:
UiState
sealed class PlayerUiState {
data object Loading: PlayerUiState()
data object Creation: PlayerUiState()
data class Edition(val player: Player): PlayerUiState()
data class Error(val message: String): PlayerUiState()
}
Просмотр модели
@HiltViewModel
class PlayerViewModel @Inject constructor(
private val playerRepository: PlayerRepository,
@ApplicationContext private val context: Context
): ViewModel() {
private val _uiState = MutableStateFlow
(PlayerUiState.Loading)
val uiState: StateFlow = _uiState.asStateFlow()
fun setState(uiState: PlayerUiState) {
_uiState.value = uiState
}
fun getPlayer(playerId: Int) {
viewModelScope.launch {
playerRepository.getPlayer(playerId).onStart {
setState(PlayerUiState.Loading)
}.catch { e ->
setState(PlayerUiState.Error(
e.message ?: context.getString(R.string.msg_unknown_error)
))
}.collect { player ->
setState(PlayerUiState.Edition(player))
}
}
}
fun insertPlayer(name: String, alias: String) {
viewModelScope.launch {
playerRepository.insertPlayer(
Player(
name = name,
alias = alias
)
)
}
}
fun updatePlayer(player: Player) {
viewModelScope.launch {
playerRepository.updatePlayer(player)
}
}
Составные элементы
@Composable
fun PlayerScreen(
modifier: Modifier = Modifier,
titleRes: Int,
viewModel: PlayerViewModel = hiltViewModel(),
playerId: Int? = null,
) {
val uiState by viewModel.uiState.collectAsState()
LaunchedEffect(playerId) {
if (playerId != null) {
viewModel.getPlayer(playerId)
} else {
viewModel.setState(PlayerUiState.Creation)
}
}
PlayerScreenContent(
modifier = modifier,
titleRes = titleRes,
uiState = uiState,
onInsert = { name, alias -> viewModel.insertPlayer(name, alias) },
onUpdate = { name, alias ->
val player = (uiState as PlayerUiState.Edition).player
viewModel.updatePlayer(player.copy(name = name, alias = alias))
},
)
}
@Composable
fun PlayerScreenContent(
modifier: Modifier = Modifier,
titleRes: Int,
uiState: PlayerUiState = PlayerUiState.Loading,
onInsert: (String, String) -> Unit,
onUpdate: (String, String) -> Unit,
) {
Scaffold() { innerPadding ->
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
) {
when (uiState) {
is PlayerUiState.Loading -> CircularProgressIndicator()
is PlayerUiState.Error -> ErrorDialog(
text = uiState.message,
)
is PlayerUiState.Creation -> PlayerForm(
onSave = onInsert,
)
is PlayerUiState.Edition -> PlayerForm(
player = uiState.player,
onSave = onUpdate,
)
}
}
}
@Composable
fun PlayerForm(
player: Player? = null,
onSave: (String, String) -> Unit,
) {
var name by rememberSaveable { mutableStateOf(player?.name ?: "") }
var alias by rememberSaveable { mutableStateOf(player?.alias ?: "") }
Box(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
contentAlignment = Alignment.BottomCenter
) {
Column(
modifier = Modifier.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text(stringResource(id = R.string.text_field_name)) },
)
OutlinedTextField(
value = alias,
onValueChange = { alias = it },
label = { Text(stringResource(id = R.string.text_field_alias)) },
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.align(Alignment.BottomCenter),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(
onClick = onSave(name, alias),
enabled = name.isNotEmpty(),
) {
Text(stringResource(id = R.string.button_save))
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/789 ... kotlin-jet
Как следовать шаблонам MVVM с запечатанным классом UiState в Android (Kotlin + Jetpack Compose)? ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение