Как изменить значение Flow репозитория?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как изменить значение Flow репозитория?

Сообщение Anonymous »

Я наткнулся на эту статью:
https://proandroiddev.com/loading-initi ... 747c20ce62
В этой статье автор, описывая преимущества и недостатки различных подходов к инициализации данных, приходит к выводу, что лучше всего это делать с помощью StateFlow. Я решил попробовать, учитывая, что использую обертку UiState как общее состояние экрана, а MyRepo как источник данных:

Код: Выделить всё

sealed class UiState {
object Loading : UiState()
data class Error(val code: Int? = null, val message: String? = null) : UiState()
data class Content(val data: T) : UiState()
}

class MyRepo {
fun getMyData(): Flow {
return flow {
delay(1000)
emit(listOf("1", "2"))
}
}
}
Это моя реализация до изменений:

Код: Выделить всё

class MyViewModel1(repo: MyRepo) : ViewModel() {
data class ScreenStateUI(
val data: List = emptyList(),
val title: String = "Title",
)

private val _screenUiState: MutableStateFlow =
MutableStateFlow(UiState.Loading)
val screenUiState: StateFlow = _screenUiState.asStateFlow()

init {
viewModelScope.launch {
repo.getMyData()
.map { UiState.Content(ScreenStateUI(data = it)) }
.collectLatest {
if (it is UiState.Content) {
_screenUiState.emit(it)
}
}
}
}

fun updateTitle(title: String) {
_screenUiState.update {
if (it is UiState.Content) {
it.copy(data = it.data.copy(title = title))
} else {
it
}
}
}
}
Во время инициализации состояние загружается, и пользовательский интерфейс может подписаться на изменения через screenUiState. Это означает, что не возникнет проблем, если вам нужно использовать забавный updateTitle(title: String).
Теперь я изменил реализацию, чтобы удалить инициализацию в блоке инициализации и сделать все так, как как только пользовательский интерфейс подпишется на событие:

Код: Выделить всё

class MyViewModel2(repo: MyRepo) : ViewModel() {
data class ScreenStateUI(
val data: List = emptyList(),
val title: String = "Title",
)

val screenUiState: StateFlow by lazy {
repo.getMyData()
.map { UiState.Content(ScreenStateUI(data = it)) }
.onStart { emit(UiState.Loading) }
.catch { emit(UiState.Error(message = it.message)) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = UiState.Loading,
)
}

fun updateTitle(title: String) {
...
}
}
Итак, кажется, все выглядит нормально, и действительно, пользовательский интерфейс теперь запускает запросы только при подписке. Однако состояние больше не может быть обновлено, и, следовательно, функция updateTitle больше не может обновлять заголовок.
Что мне здесь не хватает?

Подробнее здесь: https://stackoverflow.com/questions/792 ... itory-flow
Ответить

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

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

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

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

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