Skip to content

Provides Presenter and its Tag

Yuri Shmakov edited this page Apr 11, 2017 · 4 revisions

Problem

Sometimes you want to manage presenter’s creation. Sometimes you want to base the presenter tag on some rules. For example, you have an adapter. And you want to use personal presenter for each adapter item. There each presenter depends on some input data, like item id or somethings else. You can’t solve this issue via @InjectPresenter tag-argument, because you can’t set this argument dynamically.

Solution

Moxy provide @ProvidePresenter and @ProvidePresenterTag annotations. You can apply these to methods. These allow you to generate tag dynamically and use custom presenter constructor.

If you mark some methods with these annotations, Moxy will use these for appropriate @InjectPresenter field at injection time. It's require only types and annotations parameters equals in each(null-parameters should be equals too). Otherwise Moxy will not understand, for a what field it should use these methods.

You can use both or one of these annotations in some place. Sometimes you want only dynamic tag. Sometimes you want only custom presenter creation. Sometimes both. Make what you need.

Call time

Firstly, presenters stored in map of tagpresenter instance. Each time when called MvpDelegate.onCreate(), MvpDelegate ask this storage to get presenter for each @InjectPresenter field by tag. In case this storage doesn't contains presenter with required tag, it will create presenter and then will be store it with tag and will set it to @InjectPresenter field.

@ProvidePresenterTag method will be called each time when MvpDelegate.onCreate() will be called. @ProvidePresenter method will be called from MvpDelegate.onCreate(), but only in case if PresenterStore will not contains presenter with required tag.

Examples

public class DetailsFragment extends MvpAppCompatFragment implements RepositoryView {
  public static final String ARGS_REPOSITORY = "argsRepository";

  @InjectPresenter(type = PresenterType.GLOBAL)
  RepositoryPresenter mRepositoryPresenter;

  private Repository mRepository;

  @ProvidePresenterTag(presenterClass = RepositoryPresenter.class, type = PresenterType.GLOBAL)
  String provideRepositoryPresenterTag() {
     mRepository = (Repository) getArguments().get(ARGS_REPOSITORY);
     return String.valueOf(mRepository.getId());
  }

  @ProvidePresenter(type = PresenterType.GLOBAL)
  RepositoryPresenter provideRepositoryPresenter() {
     RepositoryPresenter repositoryPresenter = new RepositoryPresenter();
     repositoryPresenter.setRepository(mRepository);
     return repositoryPresenter;
  }

  ...

Here we make PresenterType.GLOBAL presenter for each DetailsFragment of Repository. In case Presenter exists then provideRepositoryPresenter() will not be called. Otherwise it will be called.

If remove provideRepositoryPresenterTag() method, and set mRepositoryPresenter as PresenterType.LOCAL, then provideRepositoryPresenter() will be called once when fragment will be created first time.

If remove provideRepositoryPresenter() method, then in case if global Presenter with generated tag will not exists, this presenter will be created with default constructor.

Easter Egg: in case if after build your project and still @ProvidePresenter method or @ProvidePresenterTag method is not used, then Moxy can not combine @InjectPresenter and these methods.

PS: If you use PresenterFactory and have problems with move to @ProvidePresenter/@ProviePresenterTag, then write us and we can help.