Освой Паттерн Observable: Управляй Состоянием и Ас…
Паттерн Observable, известный как “наблюдатель”, используется для построения отношений “один ко многим” между объектами. Один объект (наблюдаемый) сообщает нескольким другим объектам (наблюдателям) о произошедших изменениях. Это полезно в Android для управления состоянием UI и асинхронными операциями.
Составляющие:
— Observable (наблюдаемый): Объект, который генерирует события.
— Observer (наблюдатель): Объект, который подписывается на события и получает уведомления об изменениях.
— Subscription (подписка): Механизм, позволяющий наблюдателю подписаться на наблюдаемый объект и получать уведомления.
Вот основа паттерна Observable. Но чтобы это запомнилось лучше, давайте рассмотрим пару аналогий.
Аналогии для понимания
- Подписка на газету: Представьте, что Observable — это газета, а Observer — подписчик. Газета выпускает новые номера (события), и подписчик получает их (уведомления). Если подписчик хочет перестать получать газету, он может отменить подписку (отписаться).
- Уведомления в социальных сетях: В социальных сетях, когда кто-то публикует новый пост (Observable), его подписчики (Observers) получают уведомления. Если подписчик больше не хочет получать уведомления, он может отписаться от этого пользователя.
Теперь, когда мы разобрались с базовыми понятиями, давайте перейдем к практическому использованию паттерна Observable в Android.
Основные концепции Observable в Android
В Android паттерн Observable часто используется для управления состоянием пользовательского интерфейса с помощью StateFlow и ViewModel. Теперь давайте рассмотрим, как это реализуется на практике.
// ViewModel
class MyViewModel : ViewModel() {
private val _data = MutableStateFlow("Initial value")
val data: StateFlow<String> get() = _data
fun updateData(newData: String) {
_data.value = newData
}
}
// Activity
class MyActivity : AppCompatActivity() {
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
lifecycleScope.launchWhenStarted {
viewModel.data.collect { updatedData ->
findViewById<TextView>(R.id.textView).text = updatedData
}
}
viewModel.updateData("Новое значение")
}
}ViewModel:
— Хранит данные и логику обновления.
— Использует `MutableStateFlow` для хранения наблюдаемых данных.
— Метод `updateData` обновляет значение в StateFlow.
Activity:
— Создает экземпляр ViewModel и подписывается на изменения StateFlow.
— Использует lifecycleScope и collect для обновления UI при изменении данных.
Вот мы создали реальный пример использования паттерна Observable с StateFlow. Теперь давайте рассмотрим более сложный пример.
Более сложный пример: наблюдение за изменениями списка
Допустим, у нас есть список задач, и мы хотим обновлять UI при добавлении, удалении или изменении задач.
// ViewModel
class TasksViewModel : ViewModel() {
private val _tasks = MutableStateFlow<List<Task>>(emptyList())
val tasks: StateFlow<List<Task>> get() = _tasks
fun addTask(task: Task) {
_tasks.value = _tasks.value + task
}
fun removeTask(task: Task) {
_tasks.value = _tasks.value - task
}
fun updateTask(updatedTask: Task) {
_tasks.value = _tasks.value.map { task ->
if (task.id == updatedTask.id) updatedTask else task
}
}
}
// Activity
class TasksActivity : AppCompatActivity() {
private lateinit var viewModel: TasksViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tasks)
viewModel = ViewModelProvider(this).get(TasksViewModel::class.java)
val tasksAdapter = TasksAdapter()
findViewById<RecyclerView>(R.id.recyclerView).apply {
adapter = tasksAdapter
layoutManager = LinearLayoutManager(this@TasksActivity)
}
lifecycleScope.launchWhenStarted {
viewModel.tasks.collect { tasks ->
tasksAdapter.submitList(tasks)
}
}
}
}ViewModel:
— Хранит список задач в MutableStateFlow.
— Методы addTask, removeTask, updateTask обновляют список задач.
Activity:
— Создает экземпляр ViewModel и подписывается на изменения списка задач.
— Обновляет RecyclerView с помощью адаптера при изменении списка задач.
Этот пример показывает, как можно использовать StateFlow для наблюдения за изменениями списка задач и обновления UI.
Ну чтож, теперь вы знаете чуть больше!