🗒 Задача¶
В разработке Android приложений часто используется паттерн MVVM (Model-View-ViewModel) для разделения бизнес-логики и пользовательского интерфейса. ViewModel отвечает за управление состоянием приложения и хранит данные, которые необходимы для отображения на экране.
Предположим, что у нас есть MainScreenViewModel первого экрана приложения, для инициализации которого подгружаются данные с сервера. ViewModel хранит единственное свойство mainScreenState, которое представляет собой объект внутреннего data class MainScreenState.
Состояние экрана включает два свойства: data (загружаемые данные — String) и isLoading (индикатор процесса загрузки, обычно имеет значение по умолчанию false).
Создайте data class для хранения состояния. При изменении состояния загрузки необходимо создать новый объект MainScreenState, скопировав текущее состояние и изменив значение поля isLoading.
Создайте метод loadData() в классе MainScreenViewModel, который будет имитировать процесс загрузки данных с сервера. Этот метод не должен принимать параметры и должен последовательно изменять состояние в следующем порядке:
-
отсутствие данных;
-
загрузка данных;
-
наличие загруженных данных.
❌ Ошибки¶
✏️ Комментарии¶
Давай все обернем в общий класс `MainScreenViewModel()`. И внутри ВМ будет встроенный дата класс для хранения стейта
Имитацию процесса загрузки данных предлагаю поместить в loadData(). То есть внутри сначала надо у стейта поменять состояние на isLoading true, затем инициализировать некими данными и одновременно прекратить процесс загрузки.
Делается чуть проще. В параметр copy() сразу передается свойство для изменения в копируемом стейте, таким образом в переменную сохранится объект уже со свойством isLoading = true
Пример:
var state: MainScreenState = MainScreenState()
state = state.copy(isLoading = true)
После этого печатаем промежуточный стейт
println(state)
Состояние экрана (стейт) может быть только одно в текущий конкретный момент. Условно он либо грузится, либо отображает данные. Поэтому подход со списком этих объектов тут точно не нужно использовать.
Если помнишь в уроке про дата классы упоминал про метод копирования объекта (который доступен только для дата классов) [https://kotlinlang.org/docs/data-classes.html#copying](https://kotlinlang.org/docs/data-classes.html#copying)
В задаче помимо сеттинга вью модели на самом деле акцент на применение этого метода (как позже научимся делать в реальном мобильном приложении).
Так вот у нас есть определенное состояние (стейт). Оно уже хранит какие-то загруженные данные для отображения их на экране (data). Если мы создадим новый объект стейта с нужными полями типа sLoading = false, то данные удалятся.
Поэтому применяется метод копирования предыдущего стейта. И по итогу и данные сохраняются, и в новом объекте стейта свойство isLoading (или какое нужно поменять сейчас) будет изменено.
🧾 Решение¶
class MainScreenViewModel {
var state: MainScreenState = MainScreenState()
fun loadData() {
state = state.copy(isLoading = true)
println(state)
val loadedData = "Data from server"
state = state.copy(data = loadedData, isLoading = false)
println(state)
}
data class MainScreenState(
val data: String? = null,
val isLoading: Boolean = false
)
}
fun main() {
val viewModel = MainScreenViewModel()
println(viewModel.state)
viewModel.loadData()
}