В проекте реализовано взаимодействие Fragment/Activity
и ViewModel
через State
модель. Все изменения внутри Fragment/Activity
делаются через эту модель.
Ипспользуется подход с подписками на 2 LiveData внутри ViewModel.
- Подписка на
eventsQueue
- используется для обработки событийных изменений на экране, которые не требуют сохранения состояния. Отображение ошибок вSnackbar
, навигация. - Подписка на
state
- используется для обработки измененийState
модели.
В проекте есть несколько базовых классов для удобной работы со State
внутри ViewModel
.
SingleStateViewModel<T>
- используется для экранов которые использую однуState
модель и все изменения состояния экрана происходят в рамках этой модели. В качестве типа дляSingleStateViewModel<T>
передаетсяState
модель. Для обновленияstate
используются методыupdateState
.
Пример:
data class ScreenState(val title: String, val subtitle: String)
class ScreenViewModel(private val storage: Storage) : SingleStateViewModel<ScreenState>() {
override fun getInitialState(): ScreenState {
return ScreenState(title = "", subtitle = "")//Создаем первичный State экрана
}
/*Обновление отдельных полей state*/
fun loadDataSample() {
val title = storage.getTitle()
val subtitle = storage.getSubtitle()
updateState {
copy(title = title, subtitle = subtitle)
}
}
/*Обновление всего state*/
fun additionalLoadDataSample() {
val title = storage.getTitle()
val subtitle = storage.getSubtitle()
val newState = ScreenState(title, subtitle)
updateState(newState)
}
}
MultipleStateViewModel<T>
- Используется для экранов где важно переключение состояний (конечный автомат) и не может быть одновременного отображение загрузки и данных. В качестве переключаемых состояний используется LoadingState. В качествеT
используется тип данных для отображения, или жеState
класс экрана. Работа с этим типомViewModel
максимально похожа на работу сSingleStateViewModel<T>
за исключением некоторых дополнительных методов используемых для упрощения изменений State.
Пример:
class ScreenViewModel(
private val userRepository: UserRepository
) : MultipleStateViewModel<User>() {
fun loadDataSample() {
userRepository.getUser()
.schedulersIoToMain()
.doOnSubscribe { showLoading() } //Переключаемся на состояние загрузки
.subscribe(
{ user ->
showContent(user)//Переключаемся на отображение контента
},
{
showStub(it.localizedMessage)//Переключаемся на состояние ошибки
}
)
.autoDispose()
}
}
BaseViewModel
- ViewModel в которой реализованы базовые методы работы сeventsQueue
и освобождения Rx подписок. Использовать если первые 2 типа ViewModel не подходят.