Skip to content

Commit 5245407

Browse files
authored
Update state.md
перенос в базу знаний подхода с EventsDispatcher
1 parent 3de045d commit 5245407

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

learning/state.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,4 +361,85 @@ _actions.trySend(State.Empty)
361361
- `trySend` же возвращает `Boolean`: `true` - если добавить новое значение удалось, `false` - если не удается добавить из-за превышения объема буфера значений. Это значит что если в очереди уже есть какие-то события, которые не успел получить UI, то новое просто будет утерено. Поэтому всегда следует использовать `send`.
362362

363363
## Дополнительно
364-
Для работы с событиями и состояниями у нас в компании используются возможности библиотеки [moko-mvvm](https://github.com/icerockdev/moko-mvvm). С ее помощью происходят привязки, как односторонняя, так и двусторонняя. Событиями занимается класс EventsDispatcher.
364+
Для работы с событиями и состояниями у нас в компании используются возможности библиотеки [moko-mvvm](https://github.com/icerockdev/moko-mvvm). С ее помощью происходят привязки, как односторонняя, так и двусторонняя.
365+
366+
Ранее событиями занимался класс EventsDispatcher. Подход с использованием EventsDispatcher считается устаревшим и в новых проектах мы его не используем. Ниже справочная информация на случай, если встретитесь с ним.
367+
368+
`EventDispatcher` - это класс с одной единственной задачей - гарантировать доставку события и вызов его обработчика на UI, после сигнала от `ViewModel`.
369+
370+
Во `ViewModel` объявляется интерфейс с методами, реализация которых ей нужна на платформе, например, метод для перехода на какой-нибудь экран:
371+
372+
```kotlin
373+
interface EventsListener {
374+
fun routeToMainPage()
375+
}
376+
```
377+
378+
Далее, все что остается сделать, чтобы вызвать событие на `UI` - это получить во `ViewModel` объект `eventsDispatcher` и, когда пора переходить на главный экран, послать платформе это событие простым вызовом метода:
379+
```kotlin
380+
class EventsViewModel(
381+
val eventsDispatcher: EventsDispatcher<EventsListener>
382+
) : ViewModel() {
383+
384+
fun onButtonPressed() {
385+
eventsDispatcher.dispatchEvent { routeToMainPage() }
386+
}
387+
388+
interface EventsListener {
389+
fun routeToMainPage()
390+
}
391+
}
392+
```
393+
394+
На платформах `Fragment` и `UIViewController` реализуют этот интерфейс.
395+
Пример реализации на Android:
396+
397+
```kotlin
398+
class EventsFragment: Fragment(R.layout.fragment_simple), EventsViewModel.EventsListener {
399+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
400+
super.onViewCreated(view, savedInstanceState)
401+
402+
val viewModel: EventsViewModel = getViewModel {
403+
EventsViewModel(eventsDispatcherOnMain())
404+
}
405+
406+
viewModel.eventsDispatcher.bind(lifecycleOwner = this, listener = this)
407+
}
408+
409+
override fun routeToMainPage() {
410+
TODO("some routing")
411+
}
412+
}
413+
```
414+
415+
Пример на iOS:
416+
417+
```swift
418+
class EventsViewController: UIViewController {
419+
private var viewModel: EventsViewModel!
420+
421+
override func viewDidLoad() {
422+
super.viewDidLoad()
423+
424+
viewModel = EventsViewModel(
425+
eventsDispatcher: EventsDispatcher(listener: self)
426+
)
427+
}
428+
}
429+
430+
extension EventsViewController: EventsViewModelEventsListener {
431+
func routeToMainPage() {
432+
fatalError("some routing")
433+
}
434+
}
435+
```
436+
437+
За счет интерфейса обе платформы знают, какой набор действий должны поддерживать.
438+
Если во `ViewModel` нужно будет добавить еще одно событие, и мы забудем реализовать его на какой-нибудь из платформ, компилятор выделит, что отсутствует реализация метода интерфейса.
439+
440+
:::warning
441+
442+
В `dispatchEvent` нельзя передавать лямбду из общего кода, например, для установки действия по кнопке в [AlertDialog](https://developer.android.com/reference/android/app/AlertDialog). Нельзя этого делать потому, что на Android мы не сможем ее никуда сохранить, поэтому при пересоздании экрана она пропадет.
443+
Если вам нужно установить чему-либо на платформе действие - делайте соответствующий метод во `ViewModel`.
444+
445+
:::

0 commit comments

Comments
 (0)