Mosby MVI - Как повторно использовать ведущий

Мой ведущий выглядит следующим образом:

// I'm retaining the presenter in a singleton instances map and reuse them
// because they are loading data from the internet and this should be done once 
// per app start only
public static ArticlePresenter get(Article article)
{
    if (INSTANCES.containsKey(article.id()))
        return INSTANCES.get(article.id());
    ArticlePresenter instance = new ArticlePresenter();
    INSTANCES.put(article.id(), instance);
    return instance;
}

@Override
protected void bindIntents()
{
    ArrayList<Observable<ArticlePartialStateChanges>> observables = new ArrayList<>();

    observables.add(intent(ArticleView::loadArticleIntent)
            .doOnNext(article -> L.d("intent: loadArticleIntent"))
            .flatMap(article -> AndroInteractor.loadArticle(article)
                    .map(data -> (ArticlePartialStateChanges) new ArticlePartialStateChanges.Loaded(data))
                    .startWith(new ArticlePartialStateChanges.LoadingArticle(article))
                    .onErrorReturn(ArticlePartialStateChanges.LoadingArticleError::new)
                    .subscribeOn(Schedulers.io())
            )
    );

    Observable<ArticlePartialStateChanges> allIntents = Observable.merge(observables);
    ArticleViewState initialState = ArticleViewState.builder().build();
    Observable<ArticleViewState> stateObservable = allIntents
            .scan(initialState, this::viewStateReducer)
            .observeOn(AndroidSchedulers.mainThread());
    subscribeViewState(stateObservable, ArticleView::render);
}

И мой фрагмент loadArticleIntent выглядит следующим образом:

@Override
public Observable<Article> loadArticleIntent()
{
    return Observable.just(article).doOnComplete(() -> L.d("Article loaded"));
}

Результат

Если фрагмент создается в первый раз, я получаю следующие 3 элемента:

  1. Начальное событие
  2. Событие загрузки статьи
  3. Загруженная статья или событие ошибки

Если фрагмент будет создан снова, он извлечет из карты уже существующий презентер и повторно использует из него последнее известное состояние. Затем я получаю следующее:

  1. Последнее загруженное событие
  2. Начальное событие
  3. Событие загрузки статьи
  4. Загруженная статья или событие ошибки

Это не идеально, мне нужно изменить логику, чтобы ТОЛЬКО генерировалось последнее известное состояние (то же самое поведение, которое происходит после поворота экрана).

Как я должен это решить?


person prom85    schedule 22.06.2017    source источник
comment
Не используйте докладчиков повторно. Если они выполняют сетевые операции, и вы хотите избежать их повторения, кэш должен быть размещен на сетевом уровне.   -  person Pelocho    schedule 22.06.2017


Ответы (1)


Не используйте Presenter повторно. Это не так, как это должно быть. Их повторное использование может сработать сегодня, но нет гарантии, что это сработает и в будущем.

Таким образом, вы просто хотите использовать данные, полученные из бизнес-логики, верно? По сути, вы хотите, чтобы эта часть была предварительно загружена данными AndroInteractor.loadArticle(article). Так что просто вызывайте это при запуске приложения, а не всего докладчика. Возможно, вы используете какую-то библиотеку кэша памяти/диска или просто используете BehaviorSubject внутри AndroInteractor.loadArticle(article). Он содержит последние данные (если они есть).

Таким образом, ваша проблема - это просто «проблема бизнес-логики» / «проблема кэширования данных», а не проблема «Презентатора». Следовательно, вы должны решить эту проблему на уровне бизнес-логики, а именно на уровне AndroInteractor.loadArticle(article), а не путем сохранения всего Presenter.

person sockeqwe    schedule 22.06.2017
comment
Вы совершенно правы, это, конечно, имеет больше смысла. Таким образом, я могу даже получить начальное состояние из Interactor и даже отфильтровать событие loadPageIntent, если Interactor уже имеет кешированное состояние. - person prom85; 22.06.2017