-
Notifications
You must be signed in to change notification settings - Fork 4
Запуск работы во время создания Store
- Запустить асинхронную работу по время создания Store
Допустим у нас есть задача начать загрузку в Middleware в момент создания Store, т.е мы хотим начать загрузку как только пользователь перешел на экран.
Для этого нужно использовать компонент Bootstrapper, который запускается один раз по время создания Store и которые должен вернуть Flow, т.е при помощи него можно эмулировать начальные действия пользователя.
Рассмотрим на прошлом примере с асинхронной загрузкой. Допустим мы хотим загрузить релевантный список товаров для пользователя как только тот перешел на наш экран.
class SearchStore @Inject constructor(
api: Api
) : BaseStore<Action, State, Nothing, Effect>(
initialState = State(),
bootstrapper = BootstrapperImpl(),
reducer = ReducerImpl(),
middleware = MiddlewareImpl(api)
) {
sealed class Effect {
data class Success(val goods: List<Good>) : Effect()
data class Suggests(val suggests: List<String>) : Effect()
data class Error(val throwable: Throwable) : Effect()
}
sealed class Action {
object LoadRelevant : Action()
data class Search(val query: String) : Action()
data class Apply(val query: String) : Action()
}
data class State(
val isLoading: Boolean = false,
val error: Throwable? = null,
val goods: List<Good> = emptyList(),
val suggests: List<String> = emptyList(),
)
class BootstrapperImpl : Bootstrapper<Action> {
override fun bootstrap(): Flow<Action> = flowOf(Action.LoadRelevant)
}
class ReducerImpl : Reducer<State, Effect> {
override fun reduce(state: State, effect: Effect): State = when (effect) {
is Effect.Suggests -> state.copy(suggests = effect.suggests)
is Effect.Success -> state.copy(isLoading = false, error = null, goods = effect.goods)
is Effect.Error -> state.copy(isLoading = false, error = effect.throwable)
}
}
class MiddlewareImpl(
private val api: Api
) : Middleware<Action, State, Effect> {
override fun execute(action: Action, state: State): Flow<Effect> = when (action) {
is Action.LoadRelevant -> flow { emit(api.fetchRelevantGoods()) }
.map<List<Good>, Effect> { Effect.Success(it) }
is Action.Search -> flow { emit(api.fetchGoods(action.query)) }
.map<List<Good>, Effect> { Effect.Success(it) }
.catch { error -> emit(Effect.Error(error)) }
is Action.Apply -> flow { emit(api.suggests(action.query)) }
.map { Effect.Suggests(it) }
.catch { emit(Effect.Suggests(emptyList())) }
}
}
}
Обратите внимание, что мы просто добавили новый Action и Bootstrapper, а также изменили код Middleware, т.к у нас появился новый Action. Теперь как только пользователь перейдет наш экран, будет создан Store и запустится LoadRelevant Action.