Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)
Posted 0 and 1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)相关的知识,希望对你有一定的参考价值。
前言
通过一个小的登录功能模块案例,帮助大家了解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)
上一节讲解了如何处理内存泄露,如何做基类封装。这一节学习如何使用动态代理处理重复逻辑,以及运用泛型创建M层的实例对象。
AOP思想-动态代理运用
在第二小节中我们已经提到了下面的问题:网络请求是耗时操作,我们 Presenter 层持有了 View 层的引用,也就是 Activity 的引用,在网络请求过程中,Activity被用户或者系统关闭,这时 View 相当于被摧毁了,如果不进行判断 View 引用是否为空,当数据返回时,就会造成空指针异常,所以每次都要进行判空才合理。
每次进行非空判断是不是很繁琐?能不能做统一处理?考虑使用动态代理进行处理,java动态代理需要使用接口辅助实现。这里的 View 类型是一个接口(V extends IBaseView),动态代理完全就可以做到统一的空类型判断,
public abstract class BasePresenter<V, M>
private SoftReference<V> mViewReference;
protected V mView;//mProxyView
protected M mModel;
protected void attachView(final V view)
mViewReference = new SoftReference<V>(view);
// mView = mViewReference.get();
mModel = createModel();
//AOP思想,统一做非空判断
mView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
if (mViewReference == null || mViewReference.get() == null)
return null;
Object object = method.invoke(mViewReference.get(), args);
return object;
);
protected void detachView()
mViewReference.clear();
mViewReference = null;
mView = null;
mModel = null;
protected abstract M createModel();
反射创建M层实例对象
之前的版本P层需要持有M层的引用,我们提供了createModel()抽象方法注入M的实例对象。createModel只是创建对象,每次M层的实现类都要覆盖实现这个方法。很繁琐。创建对象的过程能不能抽取封装到基类实现?有经验的或者对java有深入了解的都会想到使用反射可以做。 确实可以。看代码
我们是通过获得泛型类的父类,拿到泛型的接口类实例,所以M层需要有父类接口,因为每个M层都会实现契约类中的IModel接口,所以完全可以使用这种方式。(如果没有可以定义一个IBaseMode的空接口让每个M实现)
BasePresenter 去掉createModel()抽象方法,改用反射方式创建
public abstract class BasePresenter<V, M>
//看到很多博客这里使用软引用,其实没必要了,因为我们已经使用detachView 的方式处理了内存泄露问题了。这里看看就行,学习一下软引用的使用方式,没有实际意义
private SoftReference<V> mViewReference;
protected V mView;//mProxyView
protected M mModel;
protected void attachView(final V view)
mViewReference = new SoftReference<V>(view);
// mView = mViewReference.get();
//AOP思想,统一做非空判断
mView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
if (mViewReference == null || mViewReference.get() == null)
return null;
Object object = method.invoke(mViewReference.get(), args);
return object;
);
//通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
if (type != null)
Type[] types = type.getActualTypeArguments();
try
mModel = (M) ((Class<?>) types[1]).newInstance();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InstantiationException e)
e.printStackTrace();
protected void detachView()
mViewReference.clear();
mViewReference = null;
mView = null;
mModel = null;
需要改动的地方P层实现类,不需要LoginPresenter,泛型传入LoginModel 实例类
public class LoginPresenter extends BasePresenter<LoginContract.IView, LoginModel> implements LoginContract.IPresenter
@Override
public void onClickLogin(String username, String pwd)
mView.showProgress(true);
mModel.getUserInfo(username, pwd, new ICallBack<String>()
@Override
public void success(String data)
if (mView != null)
mView.showToast("登录成功");
mView.showProgress(false);
mView.goToMainActivity();
@Override
public void error(String error)
if (mView != null)
mView.showProgress(false);
mView.showToast("登录失败");
);
分析泛型代码如何工作
//通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
if (type != null)
Type[] types = type.getActualTypeArguments();
try
mModel = (M) ((Class<?>) types[1]).newInstance();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InstantiationException e)
e.printStackTrace();
this.getClass()我们拿到的是 LoginPresenter 类,this.getClass().getGenericSuperclass()获取到 LoginPresenter 的父类 BasePresenter 类。再接着,Type[] types = type.getActualTypeArguments()获取 BasePresenter 的泛型参数,因为这里 LoginModel 是通过 BasePresenter 类的泛型传进去,这里的BasePresenter 有两个泛型参数,它返回一个 Type[] 数组。而第二个就是我们需要的真正的 LoginModel 类对象了,最后通过类对象的 newInstance() 实例化就可以了。
这一小节学习了使用动态代理优化每次需要判空的繁琐问题,使用反射优化创建M层的繁琐代码。下一节学习如何处理 多个P层的问题。
以上是关于Android MVP-编程思想4(AOP思想-动态代理运用,反射创建M层实例对象)的主要内容,如果未能解决你的问题,请参考以下文章
Android MVP-编程思想1(什么是MVC-MVP-MVVM模式?)
Android MVP-编程思想5(如何处理多个P层的问题?)
Android MVP-编程思想5(如何处理多个P层的问题?)
Android MVP-编程思想3(MVP-内存泄露问题处理,基类封装,有没有必要再使用软引用?)