events_by_interactor.md
May 26, 2020 · View on GitHub
Рассылка событий через Interactor
Еще один кейс использования интеракторов: построение событийной модели общения между частями приложения.
Например, некоторое действие на активити А должно вызывать обновление
данных на активити Б. Причем, данное действие не является результатом активити А.
Тогда можно пробросить событие через общий интерактор у данных активити.
Данный кейс, показывает, что приоритетнее использовать именно интерактор для
обновления данных, а не результат активити(например через RouteWithParams).
Маршрут с параметрами следует использовать там, где очевиден возврат результата, например,
некая форма, которая возвращает заполненные данные на предыдущий экран.
Реализовать проброс этого события можно через создания Subject'а внутри
интерактора. При этом этот Subject должен быть приватным, а наружу должен
смотреть только соответствующий Observable.
private val someEventSubject = PublishSubject.create<SomeEvent>()
val observeSomeEvent: Observable<SomeEvent> = someEventSubject
Примечание: выбор типа сабжекта зависит от нужд приложения.
Только сам интерактор может эмитить события - презентер может лишь менять данные, но не напрямую рассылать сообщения.
Плохо:
//Presenter
fun doSomethingWithPost() {
postActionDisposable = subsribeIoHandleError(
postInteractor.doSomeActionWithPost(screenModel.postId),
{
// do something
},
{
if (it is PostDeletedError) {
handleDeletedPostError()
}
}
)
}
private fun handleDeletedPostError() {
postInteractor.emitPostDeletedEvent(screenModel.postId)
// some other actions
}
Хорошо:
//Presenter
fun doSomethingWithPost() {
postActionDisposable = subsribeIoHandleError(
postInteractor.doSomeActionWithPost(screenModel.postId),
{
// do something
},
{
//handle something error
}
)
}
//Interactor
fun doSomeActionWithPost(postId: Long) =
postRepository.doSomeWithPost()
.doOnError {
if (it is PostDeletedError) {
emitPostDeletedEvent(postId)
}
}
Может возникнуть кейс, когда экран, который вызывает изменение данных, сам подписан на изменение. Тогда следует добавить в чейн с подпиской оператор filter.
val postActionDisposable = ...
//...
postActionDisposable = subsribeIoHandleError(postInteractor.doSomeActionWithPost(screenModel.postId),
{
// do something
})
//...
postChangedEventDisposable = subscribe(interactor.observePostChangedEvent
.filter { postActionDisposable.isDisposed },
{
// OnSuccess
})
Таким образом можно офильтровать событие по активности запроса, который вызывает изменение данных, чтобы оно не хендлилось на текущем экране.