[原创]AndroidMVP模式之:通过注解绑定Presenter

Github地址android-presenter

MVP优点:view由Activity承担,Presenter做业务,结构清晰(模式么就是讲究一个套路,结构清晰后来者维护也是受益的)。之前开发都是全写一个类-Activity里面,业务复杂的情况下看着头疼。理想化Presenter层应该是不包含android代码,使junit,我是没使用。

通过注解绑定Presenter:一般情况下每个view有个presenter ,代码量也就多了。那如何将Presenter重用起来呢?答案就是通过注解了。

看代码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindP {

    @SuppressWarnings("rawtypes")
    Class<? extends Presenter>[] value();

}

我们再来看看Presenter

public abstract class Presenter<V> {
    //view
    private V view;
    //isAttached
    private boolean isAttached = false;

    /**
     * getViewInstance
     *
     * @return view
     */
    protected final V getViewInstance() {
        return view;
    }

    /**
     * isAttached
     *
     * @return isAttached
     */
    public final boolean isAttached() {
        return isAttached;
    }

    /**
     * attach
     *
     * @param view view
     */
    public void onAttach(V view) {
        this.view = view;
        isAttached = true;
    }

    /**
     * dettach
     */
    public void onDettach() {
        isAttached = false;
        view = null;
    }

    /**
     * response
     *
     * @param data data
     * @param <D>  data type
     * @return callback
     */
    protected <D> Response1<D> response(D data) {
        return new Response1<D>(data);
    }

    /**
     * response
     *
     * @return callback
     */
    protected Response response() {
        return new Response();
    }

    /**
     * Response
     */
    protected class Response {
        /**
         * back
         *
         * @param action back
         */
        public Response back(OnAction action) {
            if (isAttached() && action != null && getViewInstance() != null) {
                action.action(getViewInstance());
            }
            return this;
        }
    }

    /**
     * Response1
     *
     * @param <D> data type
     */
    protected class Response1<D> {

        private D data;

        public Response1(D data) {
            this.data = data;
        }

        public <C> Response1<C> map(OnMap<D, C> map) {
            return new Response1<C>(map.map(data));
        }

        /**
         * back
         *
         * @param callback callback
         */
        public Response1<D> back(OnCallback<D> callback) {
            if (isAttached() && callback != null && getViewInstance() != null) {
                callback.callback(getViewInstance(), data);
            }
            return this;
        }
    }

    /**
     * OnAction
     */
    protected abstract class OnAction {
        public abstract void action(V view);
    }

    /**
     * OnMap
     *
     * @param <D> data type
     * @param <C> to type
     */
    protected abstract class OnMap<D, C> {
        public abstract C map(D data);
    }

    /**
     * OnCallback
     *
     * @param <D> data type
     */
    protected abstract class OnCallback<D> {
        public abstract void callback(V view, D data);
    }
}

从代码我们可以看出,Presenter的生命周期函数只有两个onAttach()onDettach()分别表示与View的绑定与解除绑定事件。

将Presenter绑定到View中

public class PresenterBind {

    private PresenterBind() {
    }

    /**
     * bindPresenter
     *
     * @param object object
     * @return presenter holder
     */
    @SuppressWarnings("rawtypes")
    public static PresenterHolder bind(Object object) {
        PresenterHolder handler = new PresenterHolder();
        if (object == null)
            return handler;
        Class<?> clazz = object.getClass();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            BindP presenter = clazz.getAnnotation(BindP.class);
            if (presenter != null) {
                Class<? extends Presenter>[] presenterTypes = presenter.value();
                for (Class<? extends Presenter> presenterType : presenterTypes) {
                    if (verifyPresenter(presenterType, object.getClass())) {
                        try {
                            Presenter pre = presenterType.getConstructor().newInstance();
                            handler.addPresenter(pre);
                        } catch (Exception e) {
                        }
                    }
                }
            }
        }
        handler.onAttach(object);
        return handler;
    }

    /**
     * addPresenter
     *
     * @param handler    holder
     * @param presenters presenters
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void bind(PresenterHolder handler, Class<? extends Presenter>... presenters) {
        if (handler == null || handler.getTarget() == null || presenters == null)
            return;
        for (Class<? extends Presenter> presenterType : presenters) {
            if (verifyPresenter(presenterType, handler.getTarget().getClass())) {
                if (!handler.hasPresenter(presenterType)) {
                    try {
                        Presenter pre = presenterType.getConstructor().newInstance();
                        handler.addPresenter(pre);
                        pre.onAttach(handler.getPersenters());
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    /**
     * verifyPresenter
     *
     * @param presenter presenter
     * @param viewClass viewClass
     * @return false or true
     */
    @SuppressWarnings("rawtypes")
    private static boolean verifyPresenter(Class<? extends Presenter> presenter, Class<?> viewClass) {
        Class<?> viewPresenterClass = getViewClass(presenter);
        if (isClassGeneric(viewClass, viewPresenterClass.getName()))
            return true;
        return false;
    }

    /**
     * getViewClass
     *
     * @param presenter presenter
     * @return view class
     */
    @SuppressWarnings("rawtypes")
    private static Class<?> getViewClass(Class<? extends Presenter> presenter) {
        if (presenter != null) {
            Class<?> entityClass = null;
            Type t = presenter.getGenericSuperclass();
            if (t instanceof ParameterizedType) {
                Type[] p = ((ParameterizedType) t).getActualTypeArguments();
                entityClass = (Class<?>) p[0];
            }
            return entityClass;
        }
        return null;
    }

    /**
     * isGeneric
     *
     * @param clazz clazz
     * @param name  name
     * @return true or false
     */
    private static boolean isClassGeneric(Class<?> clazz, String name) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            if (name.equals(clazz.getName())) {
                return true;
            }
            Class<?>[] classes = clazz.getInterfaces();
            for (int i = 0; i < classes.length; i++) {
                if (name.equals(classes[i].getName())) {
                    return true;
                }
            }
        }
        return false;
    }
}

我们通过PresenterBind.bind(Object object) 解析并实例化Presenter,返回PresenterHolder 作为Presenter的持有者。

public class PresenterHolder {
    @SuppressWarnings("rawtypes")
    private Map<String, Presenter> persenterMap = new HashMap<String, Presenter>();
    // is attached
    private boolean isAttached = false;
    //target
    private Object target = null;

    /**
     * getTarget
     *
     * @return target
     */
    public Object getTarget() {
        return target;
    }

    /**
     * putPresenter
     *
     * @param presenter presenter
     */
    @SuppressWarnings("rawtypes")
    protected void addPresenter(Presenter presenter) {
        if (presenter == null) {
            return;
        }
        if (hasPresenter(presenter.getClass())) {
            return;
        }
        persenterMap.put(presenter.getClass().getName(), presenter);
    }

    /**
     * onAttach
     *
     * @param object object
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public void onAttach(Object object) {
        if (isAttached) {
            return;
        }
        if (!isEmpty()) {
            for (Map.Entry<String, Presenter> entry : persenterMap.entrySet()) {
                entry.getValue().onAttach(object);
            }
        }
        target = object;
        isAttached = true;
    }

    /**
     * isAttached
     *
     * @return is attached
     */
    public boolean isAttached() {
        return isAttached;
    }

    /**
     * onDettach
     */
    @SuppressWarnings("rawtypes")
    public void onDettach() {
        if (isAttached) {
            for (Map.Entry<String, Presenter> entry : persenterMap.entrySet()) {
                entry.getValue().onDettach();
            }
            persenterMap.clear();
            isAttached = false;
        }
    }

    /**
     * isEmpty
     *
     * @return is empty
     */
    public boolean isEmpty() {
        return persenterMap.isEmpty();
    }

    /**
     * getPersenters
     *
     * @return persenterMap
     */
    @SuppressWarnings("rawtypes")
    public Map<String, Presenter> getPersenters() {
        return persenterMap;
    }

    @SuppressWarnings("rawtypes")
    public boolean hasPresenter(Class<? extends Presenter> cls) {
        if (persenterMap.containsKey(cls.getName())) {
            return true;
        }
        return false;
    }

    /**
     * getPresenter
     *
     * @param clazz clazz
     * @param <T>   t
     * @return presenter
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public <T extends Presenter> T getPresenter(Class<T> clazz) {
        if (hasPresenter(clazz)) {
            return (T) persenterMap.get(clazz.getName());
        }
        return null;
    }
}

具体使用

创建Presenter

public class BasePresenter extends Presenter<BasePresenter.IView> {

    public static interface IView {
        void toast(String s);
    }

    public void showToast() {
        response("show toast").back(new OnCallback<String>() {
            @Override
            public void callback(IView view, String data) {
                view.toast(data);
            }
        });
    }
}

使用Presenter

@BindP(BasePresenter.class)
public class MainActivity extends AppCompatActivity implements BasePresenter.IView {

    private PresenterHolder holder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        holder = PresenterBind.bind(this);
        holder.getPresenter(BasePresenter.class).exec();
    }

    @Override
    public void toast(String s) {
        Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        holder.onDettach();
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值