package com.arellomobile.mvp; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.arellomobile.mvp.presenter.PresenterField; import com.arellomobile.mvp.presenter.PresenterType; /** * Date: 18-Dec-15 * Time: 13:16 * * @author Yuri Shmakov * @author Alexander Blinov */ public class MvpProcessor { public static final String PRESENTER_BINDER_SUFFIX = "$$PresentersBinder"; public static final String PRESENTER_BINDER_INNER_SUFFIX = "Binder"; public static final String VIEW_STATE_SUFFIX = "$$State"; public static final String VIEW_STATE_PROVIDER_SUFFIX = "$$ViewStateProvider"; /** * <p>1) Generates tag for identification MvpPresenter</p> * <p>2) Checks if presenter with tag is already exist in {@link com.arellomobile.mvp.PresenterStore}, and returns it</p> * <p>3) If {@link com.arellomobile.mvp.PresenterStore} doesn't contain MvpPresenter with current tag, {@link PresenterField} will create it</p> * * @param <Delegated> type of delegated * @param target object that want injection * @param presenterField info about presenter from {@link com.arellomobile.mvp.presenter.InjectPresenter} * @param delegateTag unique tag generated by {@link MvpDelegate#generateTag()} @return MvpPresenter instance */ private <Delegated> MvpPresenter<? super Delegated> getMvpPresenter(Delegated target, PresenterField<Delegated> presenterField, String delegateTag) { Class<? extends MvpPresenter<?>> presenterClass = presenterField.getPresenterClass(); PresenterStore presenterStore = MvpFacade.getInstance().getPresenterStore(); PresenterType type = presenterField.getPresenterType(); String tag; if (type == PresenterType.LOCAL) { tag = delegateTag + "$" + presenterField.getTag(target); } else { tag = presenterField.getTag(target); } //noinspection unchecked MvpPresenter<? super Delegated> presenter = presenterStore.get(tag); if (presenter != null) { return presenter; } //noinspection unchecked presenter = (MvpPresenter<? super Delegated>) presenterField.providePresenter(target); if (presenter == null) { return null; } presenter.setPresenterType(type); presenter.setTag(tag); presenter.setPresenterClass(presenterClass); presenterStore.add(tag, presenter); return presenter; } /** * <p>Gets presenters {@link java.util.List} annotated with {@link com.arellomobile.mvp.presenter.InjectPresenter} for view.</p> * <p>See full info about getting presenter instance in {@link #getMvpPresenter}</p> * * @param delegated class contains presenter * @param delegateTag unique tag generated by {@link MvpDelegate#generateTag()} * @param <Delegated> type of delegated * @return presenters list for specifies presenters container */ <Delegated> List<MvpPresenter<? super Delegated>> getMvpPresenters(Delegated delegated, String delegateTag) { if (!hasMoxyReflector()) { return Collections.emptyList(); } @SuppressWarnings("unchecked") Class<? super Delegated> aClass = (Class<Delegated>) delegated.getClass(); List<Object> presenterBinders = null; while (aClass != Object.class && presenterBinders == null) { presenterBinders = MoxyReflector.getPresenterBinders(aClass); aClass = aClass.getSuperclass(); } if (presenterBinders == null || presenterBinders.isEmpty()) { return Collections.emptyList(); } List<MvpPresenter<? super Delegated>> presenters = new ArrayList<>(); PresentersCounter presentersCounter = MvpFacade.getInstance().getPresentersCounter(); for (Object presenterBinderObject : presenterBinders) { //noinspection unchecked PresenterBinder<Delegated> presenterBinder = (PresenterBinder<Delegated>) presenterBinderObject; List<PresenterField<Delegated>> presenterFields = presenterBinder.getPresenterFields(); for (PresenterField<Delegated> presenterField : presenterFields) { MvpPresenter<? super Delegated> presenter = getMvpPresenter(delegated, presenterField, delegateTag); if (presenter != null) { presentersCounter.injectPresenter(presenter, delegateTag); presenters.add(presenter); presenterField.bind(delegated, presenter); } } } return presenters; } private static Boolean hasMoxyReflector = null; // Check is it have generated MoxyReflector without usage of reflection API private static boolean hasMoxyReflector() { if (hasMoxyReflector != null) { return hasMoxyReflector; } try { new MoxyReflector(); hasMoxyReflector = true; } catch (NoClassDefFoundError error) { hasMoxyReflector = false; } return hasMoxyReflector; } }