Android MVP-编程思想7(为什么使用代理类抽取通用方法而不是工具类?,基类BaseMvpFragment)

前言

通过一个小的登录功能模块案例,帮助大家了解MVP。最终实现一个结合Rxjava2,Retrofit 的MVP通用框架。代码放到github上。(如有错误之处,请在评论区指出,谢谢。如果感觉写的不错,请点赞,关注,谢谢。)

目录:

Android MVP-编程思想1(什么是MVC-MVP-MVVM模式?)
Android MVP-编程思想2(代码实现初级版)
Android MVP-编程思想3(内存泄露问题处理,基类封装,有没有必要再使用软引用?)
Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)
Android MVP-编程思想5(如何处理多个P层的问题?)
Android MVP-编程思想6(依赖注入多个P层优化—注解,反射)
Android MVP-编程思想7(为什么使用代理类抽取通用方法而不是工具类?,基类BaseMvpFragment)

未完待续--------
Android MVP-编程思想8(集成Rxjava2,Retrofit)

上一小节使用注解和反射优化了P层依赖注入的方式。这一节学习基类BaseMvpFragment,代理类抽取通用方法.
BaseMvpFragment 和BaseMvpActivity 都属于V层的封装,有很多通用的代码,比如注入P层的代码。如何把这些代码抽离复用呢? 很多程序员首先想到的就是做成工具类。当然这种方式也可以,但是总是感觉不优雅。因为,当很多地方都需要使用的情况下我们才会做成工具类,而且工具类一般不依赖系统架构,这里只是两个地方用,而且是服务于MVP架构的代码块。所以做成工具类不太优雅。
还有没有别的方式?

不使用工具类?代理类抽取通用代码

定义代理接口

因为只是抽离P层 注入和销毁的代码所以可以抽象出两个行为接口,如下

public interface IMvpProxy {
    void bindPresenter();

    void unbindPresenter();
}

代理接口实现类

public class MvpProxyImpl<V extends IBaseView> implements IMvpProxy {
    private V mView;
    private List<BasePresenter> mPresenters;

    public MvpProxyImpl(V view) {
        this.mView = view;
        mPresenters = new ArrayList<>();
    }

    @Override
    public void bindPresenter() {
        //获得已经申明的变量,包括私有的
        Field[] fields = mView.getClass().getDeclaredFields();
        for (Field field : fields) {
            //获取变量上面的注解类型
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                try {
                    Class<? extends BasePresenter> type = (Class<? extends BasePresenter>) field.getType();
                    BasePresenter mInjectPresenter = type.newInstance();
                    mInjectPresenter.attachView(mView);
                    field.setAccessible(true);
                    field.set(mView, mInjectPresenter);
                    mPresenters.add(mInjectPresenter);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (ClassCastException e) {
                    e.printStackTrace();
                    throw new RuntimeException("SubClass must extends Class:BasePresenter");
                }
            }
        }
    }

    @Override
    public void unbindPresenter() {
        /**
         * 解绑,避免内存泄漏
         */
        for (BasePresenter presenter : mPresenters) {
            presenter.detachView();
        }
        mPresenters.clear();
        mPresenters = null;
    }

}

BaseMvpActivity代码

public abstract class BaseMvpActivity extends AppCompatActivity {
    private MvpProxyImpl mvpProxy;
    protected List<BasePresenter> mPresenters;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView;
        final Object layout = getLayout();
        if (layout instanceof Integer) {
            rootView = View.inflate(this, (int) getLayout(), null);
        } else if (layout instanceof View) {
            rootView = (View) getLayout();
        } else {
            throw new ClassCastException("type of setLayout() must be int or View!");
        }
        setContentView(rootView);
        mvpProxy = createProxy();
        mvpProxy.bindPresenter();
        afterCreate();
    }

    private MvpProxyImpl createProxy() {
        if (mvpProxy == null) {
            return new MvpProxyImpl<>((IBaseView) this);
        }
        return mvpProxy;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        for (BasePresenter p : mPresenters) {
            p.detachView();
        }
        mvpProxy.unbindPresenter();
        mPresenters.clear();
        mPresenters = null;
    }

    @SuppressWarnings("ConstantConditions")
    protected <T extends View> T $(@IdRes int viewId) {
        return findViewById(viewId);
    }

    public void showProgress(boolean isShow) {
        if (isShow) {
            Log.i("mvp_", "显示等待框");
        } else {
            Log.i("mvp_", "隐藏等待框");
        }
    }

    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    protected abstract Object getLayout();

    protected abstract void afterCreate();
}

BaseMvpFragment 代码

public abstract class BaseMvpFragment extends Fragment {
    private MvpProxyImpl mvpProxy;
    public Activity mActivity;
    private View mRootView;

    protected abstract @LayoutRes
    int getLayoutId();

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mActivity = (Activity) context;
    }

    @SuppressWarnings("ConstantConditions")
    protected <T extends View> T $(@IdRes int viewId) {
        return this.getView().findViewById(viewId);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mRootView == null) {
            try {
                mRootView = inflater.inflate(getLayoutId(), container, false);
            } catch (Resources.NotFoundException e) {
                e.printStackTrace();
            }
            throw new RuntimeException("根布局的id非法导致根布局为空,请检查后重试!");
        }
        mvpProxy = createProxy();
        mvpProxy.bindPresenter();
        return mRootView;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        afterCreate();
    }

    private MvpProxyImpl createProxy() {
        if (mvpProxy == null) {
            return new MvpProxyImpl<>((IBaseView) this);
        }
        return mvpProxy;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mvpProxy.unbindPresenter();
    }

    protected abstract void afterCreate();
}

你可能感兴趣的:(architectural,thinking)