Как следовать шаблонам MVVM с запечатанным классом UiState в Android (Kotlin + Jetpack Compose)?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как следовать шаблонам MVVM с запечатанным классом UiState в Android (Kotlin + Jetpack Compose)?

Сообщение Anonymous »

Я создал приложение для 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»