Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
android反射调用_反射变换矩阵公式,希望能够帮助你!!!。
这篇是基于上篇(Android MVP 架构(三)MVP 内存泄漏分析与动态代理)的 BaseMVP 框架基础上进行配置和修改的,上篇我们介绍了 MVP 可能存在的内存泄漏的问题,还有就是如何使用动态代理,我们把同一段代码或同一个业务逻辑判断操作项抽离出来,用的就是 AOP 思想。AOP 思想的一种编程手段,使用动态代理的方式进行抽离重复的代码或进行统一的逻辑处理。
使用动态代理对 View 层进行抽离统一的逻辑判断,这一项工作我们在上篇文章中已经完成了。紧接着,我们就应该考虑其他层的封装处理。这篇文章,我们就拿 Model 层开刀。
首先,看看我们的 BaseMVP 框架中的 Model 层,Model 虽然提供数据源都各不相同,但每次引用它时,都需要在 Presenter 层拿到它的引用才行,最简单的引用方式是 new 出它的实例,比如下面的 MianPresenter 中的代码:
/** * presenter 层,承担业务逻辑处理,数据源处理等 */ public class MainPresenter extends BasePresenter<MainContract.IMainView> implements MainContract.IMainPresenter { private MainContract.IMainModel mModel; @Override public void attech(IBaseView view) { super.attech(view); mModel = new DataModel(); } @Override public void handlerData() { getView().showDialog(); mModel.requestBaidu(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String content = response.body().string(); getView().succes(content); } }); } @Override public void detech() { super.detech(); /** * 释放内存、关闭网络请求、关闭线程等操作 */ Log.d("==========", "detech: 解除绑定,释放内存"); } }
就像代码中的 IMainModel 接口,我们每次要获取数据源时,都要去 new 它的一个实现类,这种方法都是可以的。但是,每次去 new 又显得麻烦,而且通常来说,一个 Presenter 和一个 Model 是一对一的关系,所以,我们想到了创建对象的另一种方式:通过反射来获取。
首先,分析一下每一个 Model 肯定是不同的类型,这里就必须用到泛型。又因为 Model 层只有与 Presenter 层才有引用的关系,Presenter 持有 Model 的引用,所以这里的 Presenter 所持有的必定是一个泛型的 Model ,而不是具体的。而且我们是写 BaseMVP 框架,所以泛型应该封装到 BasePresenter 基类中去,才能让实现它的子类去调用。
于是呢,我们的第一步,创建 BaseModel 基类,这里没有什么新的方法,主要用于泛型与继承的关系。如果有什么比较特殊的数据源或通用的可以在基类中提供。
第4个版本我们与前3个版本对比,就添加了一个 BaseModel 类,来看看包详情
第二步,我们的 DataModel 就要继承 BaseModel 基类,提供相应的 Presenter 提供特有的数据。
修改 DataModel 实现类:
package com.test.mvp.mvpdemo.mvp.v4.model; import com.test.mvp.mvpdemo.mvp.v4.MainContract; import com.test.mvp.mvpdemo.mvp.v4.basemvp.BaseModel; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; /** * model 层,请求网络或数据库,提供数据源(原始数据) */ public class DataModel extends BaseModel implements MainContract.IMainModel { @Override public void requestBaidu(Callback callback) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.baidu.com/") .build(); client.newCall(request).enqueue(callback); } }
接下来,就是我们的重点:BasePresenter 类的修改与处理,我们要为 BasePresenter 类再添加一个泛型参数,提供对不同 Model 实现类的支持。再者,就是使用反射来实例化 Model 对象,这里可能是比较容易出错的。一个是对反射的理解,另一个是对泛型的理解。我们先看看代码,再进行解释。
修改 BasePresenter 基类:
package com.test.mvp.mvpdemo.mvp.v4.basemvp; import android.util.Log; import java.lang.ref.SoftReference; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; public abstract class BasePresenter<V extends IBaseView, M extends BaseModel> implements IBasePresenter { private SoftReference<IBaseView> mReferenceView; private V mProxyView; private M mModel; @SuppressWarnings({"unchecked", "TryWithIdenticalCatches"}) @Override public void attach(IBaseView view) { //使用软引用创建对象 mReferenceView = new SoftReference<>(view); //使用动态代理做统一的逻辑判断 aop 思想 mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { if (mReferenceView == null || mReferenceView.get() == null) { return null; } return method.invoke(mReferenceView.get(), objects); } }); //通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 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(); } } } @SuppressWarnings("unchecked") public V getView() { return mProxyView; } protected M getModel() { return mModel; } @Override public void detach() { mReferenceView.clear(); mReferenceView = null; } }
先看类的参数,我们添加了一个继承自刚刚写的 BaseModel 类的泛型参数,这里不难理解。可能比较难理解的是如何实例化 Model 对象吧,也就是这个例子中的 DataModel 类的实例化。
既然这样,我们先来看看在 MainPresenter 实现类中该如何传递这个泛型 Model ,应该是传入 DataModel 吧,来看看我们的MainPresenter 类代码:
修改 MainPresenter 实现类:
/** * presenter 层,承担业务逻辑处理,数据源处理等 */ public class MainPresenter extends BasePresenter<MainContract.IMainView, DataModel> implements MainContract.IMainPresenter { @Override public void handlerData() { getView().showDialog(); getModel().requestBaidu(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { String content = response.body().string(); getView().succes(content); } }); } @Override public void detach() { super.detach(); /** * 释放内存、关闭网络请求、关闭线程等操作 */ Log.d("==========", "detech: 解除绑定,释放内存"); } }
这里我们传入的是 DataModel 的实例,而 MainPresenter 类是继承自 BasePresenter 基类的,所以在 BasePresenter 的反射代码中的 this 指的就是 MainPresenter 类的对象。看如下反射代码:
反射代码部分:
//通过获得泛型类的父类,拿到泛型的接口类实例,通过反射来实例化 model ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); Log.d("===========", "attach: "+this.getClass().getSimpleName()); if (type != null) { Type[] types = type.getActualTypeArguments(); try { mModel = (M) ((Class<?>) types[1]).newInstance(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } }
通过 Log 打印就能验证一下,看看是否正确。
我们拿到的是 MainPresenter 类的对象,这不是我们想要的啊,我们想要的是 DataModel 类的对象。又因为这里 DataModel 是通过 BasePresenter 类的泛型传进去的,所以我们通过反射机制是可以获取到 MainPresenter 的父类 BasePresenter 类。再接着,我们应该去获取 BasePresenter 的泛型参数,这里的 BasePresenter 有两个泛型参数,它返回一个 Type[] 数组。而第二个就是我们需要的真正的 DataModel 类对象了,最后通过类对象的 newInstance() 实例化就可以了。
看起来是有点难理解,不过还是 Java 的基础啊,正是运用了 Java 的反射来动态的创建 Model 层,这是我们写框架的必备知识。那么,到这里我们又解决了 Model 层需要手动 new 来实例化的问题,通过反射可以让我们的代码变得更加的优雅,看起来也比较舒服。当然,对于初学者来说,这样的代码看起来是有点难理解,还是要死磕到底啊。
码字不易,看到这里别只点收藏啊,动动小手关注一下小编呗。
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
下一篇
已是最新文章