badoo / MVICore

MVI framework with events, time-travel, and more
https://badoo.github.io/MVICore/
Other
1.27k stars 90 forks source link

Bootstraper starts working before newsListener was binded with view and feature #121

Closed antonij-ub closed 4 years ago

antonij-ub commented 4 years ago

Привет. Столкнулись с такой проблемой. В Bootstraper вызывается invoke() до того, как newsListener будет связан с представлением и фичей и из за этого мы пропускаем событие, отправленное при старте запроса (Observable.startWith()) Как результат - ProgressDialog не будет показан при старте запроса. Как можно решить эту проблему?

class ToursToHotelFeature(
    api: Api
) : ActorReducerFeature<ToursToHotelFeature.Wish, ToursToHotelFeature.Effect, ToursToHotelFeature.State, ToursToHotelFeature.News>(
    initialState = State(),
    actor = ActorImpl(api),
    reducer = ReducerImpl(),
    newsPublisher = NewsPublisherImpl(),
    bootstrapper = BootstraperImpl()
) {

    class BootstraperImpl() : Bootstrapper<Wish> {
        override fun invoke(): Observable<Wish> = Observable.just(Wish.StartSearch)
    }

    data class State(...)

    sealed class Wish {
        object StartSearch : Wish()
    }

    sealed class News {
        data class ShowProgressBar(val show: Boolean) : News()
    }

    sealed class Effect {
        object StartedLoading : Effect()
        data class FinishWithError(val error: Throwable) : Effect()
    }

    class ActorImpl(val api: ApiService.TourApi) : Actor<State, Wish, Effect> {
        override fun invoke(state: State, wish: Wish): Observable<Effect> = when (wish) {
            Wish.StartSearch -> {
                   api.someRequest()
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .startWith(Effect.StartedLoading)
                        .doOnError { Effect.FinishWithError(it) }
                        .onErrorReturn { Effect.FinishWithError(it) }
            }
        }
    }

    class NewsPublisherImpl : NewsPublisher<Wish, Effect, State, News> {
        override fun invoke(action: Wish, effect: Effect, state: State): News? {
            return when (effect) {
                Effect.StartedLoading -> News.ShowProgressBar(true)
                is Effect.FinishWithError -> News.ShowProgressBar(false)
                else -> null
            }
        }
    }
}
zsoltk commented 4 years ago

Speak English please.

  1. Read https://badoo.github.io/MVICore/features/bootstrappers/
  2. Read https://badoo.github.io/MVICore/bestpractices/delayingbootstrapping/
  3. Your case looks like a misuse of News. Use State.