Pablo
05/29/2024, 11:13 AMmutablestate
uistate to set current selected item in a viewmodel? I have this uistate class, and need to change selectedBookId
value.
sealed interface BooksGridUiState {
data class Success(
val booksList: List<BookData>,
val selectedBookId: String?
) : BooksGridUiState
object Error : BooksGridUiState
object Loading : BooksGridUiState
}
var uiState: BooksGridUiState by mutableStateOf(BooksGridUiState.Loading)
private set
Can't do the trick of calling
.update {
it.copy(
Because this is not a mutablestateflow
, and I'm following a codelab and must use mutablestate
Pablo
05/29/2024, 11:27 AMfun selectBook(id: String) {
(uiState as BooksGridUiState.Success).let {
uiState = BooksGridUiState.Success(it.booksList, id)
}
}
Pablo
05/29/2024, 11:29 AMfun selectBook(id: String) {
(uiState as BooksGridUiState.Success).let {
uiState = it.copy(selectedBookId = id)
}
}
vide
05/29/2024, 12:36 PMPablo
05/29/2024, 2:01 PMsealed interface BooksGridUiState {
data class Success(
val booksList: List<BookData>,
val selectedBookId: String? = null
) : BooksGridUiState
object Error : BooksGridUiState
object Loading : BooksGridUiState
}
class BooksGridViewModel(
val bookshelfRepository: BookshelfRepository
): ViewModel() {
var uiState: BooksGridUiState by mutableStateOf(BooksGridUiState.Loading)
private set
init {
getBooks()
}
private fun getBooks() {
viewModelScope.launch {
try {
uiState = BooksGridUiState.Success(bookshelfRepository.getBooks())
} catch (e: Exception) {
e.printStackTrace()
uiState = BooksGridUiState.Error
}
}
}
fun selectBook(id: String?) {
(uiState as? BooksGridUiState.Success)?.let {
uiState = it.copy(selectedBookId = id)
}
}
/**
* Factory for this viewmodel that takes repository as a dependency
*/
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
val application = (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as BookshelfApplication)
val repository = application.container.booksRepository
BooksGridViewModel(repository)
}
}
}
}
vide
05/29/2024, 3:28 PMvide
05/29/2024, 3:29 PMe.printStackTrace()
prints to stderr instead of logcat.vide
05/29/2024, 3:30 PMPablo
05/29/2024, 4:12 PMZach Klippenstein (he/him) [MOD]
05/30/2024, 12:13 AMPablo
05/30/2024, 7:52 AMAnselmo Alexandre
05/30/2024, 11:14 AMsealed interface
, not data class.
So for you to be able to update the selectedBookId
, you need to create a new Success UiState
with the selectedBookId you want to update.vide
05/30/2024, 11:27 AMi thought that all the values inside the uistate should be val, not varIt's sometimes convenient to have a single UI state object (with no sub-state) but it doesn't have to be so in every case. It's difficult to give definite guidelines because there are so many different possible scenarios. For example if your data has several subsections that usually change as a group or very frequently, it might make sense to extract those to a separate state.
vide
05/30/2024, 11:29 AM.update()
cannot be used because the object is not a MutableStateFlow
, which has the extension method:
public inline fun <T> MutableStateFlow<T>.update(function: (T) -> T)
Anselmo Alexandre
05/30/2024, 11:34 AMcopy()
selectedBookId
to the already existing uiState. Right?vide
05/30/2024, 11:36 AMAnselmo Alexandre
05/30/2024, 11:39 AMvide
05/30/2024, 11:41 AMuiState = BooksGridUiState.Success(it.booksList, id)
uiState = it.copy(selectedBookId = id)
Anselmo Alexandre
05/30/2024, 11:51 AMuiState = BooksGridUiState.Success(it.booksList, id)So this was what I was referring to, create a hole new instance of BooksGridUiState.Success and then update it, because he wouldn’t be able to use copy() on sealed class/interface.
uiState = it.copy(selectedBookId = id)For this style to be achieved, he would have to declare the BooksGridUiState has data class, like
data class BooksGridUiState(…)
, so afterwards on new uiState, inside the .update{ it.copy(selectedBookId = id) }
vide
05/30/2024, 11:56 AMBooksGridUiState
but you can create new instances of Success
.
it.copy(selectedBookId = id)
works just fine!vide
05/30/2024, 11:57 AMSuccess
is not sealed, right?vide
05/30/2024, 11:57 AMval a = object : BooksGridUiState { }
Anselmo Alexandre
05/30/2024, 11:58 AMZach Klippenstein (he/him) [MOD]
05/30/2024, 5:08 PMi thought that all the values inside the uistate should be val, not varThis may depend on your architecture, but all that compose requires is that if they’re
var
, that they’re backed by snapshot state