第三方库探究|Retrofit是如何创建的(为什么要用动态代理)

Retrofit的出现让Android的网络请求变得异常简单,同时可以很好的配合后台的REST接口。非常值得我们去探究一下它的原理。
Retrofit的使用 通常我们是Retrofit是和Rxjava配合使用,这里我们不做用法上的过多研究,主要看原理,所以下面的代码都是Retrofit的自身API,没有用Rxjava。
下面是一个普通get请求
1.新建接口
新建接口API.java文件:
public interface API { @GET("请求地址,但是不包括服务器的地址") Call get( @Query("param1") String param1,//第一个参数 @Query("param2") int param2); //第二个参数 }

在@GET注解里面加上除去服务器链接的请求地址,@Query注解里面是请求的参数名。
2.创建Retrofit服务和请求客户端
新建一个单例类,RetrofitService.java(名字随意),在里面定义一个静态的OkHttpClient
private RetrofitService() {//构造方法私有化 }public static RetrofitService getInstance() {//双重校验 if (instance == null) { synchronized (RetrofitService.class) { if (instance == null) { instance = new RetrofitService(); } } } return instance; }private static OkHttpClient mOkHttpClient; private static void initOkHttpClient() { HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(); //日志拦截器 mOkHttpClient = new OkHttpClient.Builder().cache(cache) .addInterceptor(logInterceptor)//日志拦截器,按照需要添加 .connectTimeout(10, TimeUnit.SECONDS).build(); //连接超时时间 }

向外提供一个方法,用于获取刚才的API接口
private volatile static API aPI = null; public static API createAPI() { if (aPI == null) { synchronized (RetrofitService.class) { if (aPI == null) { initOkHttpClient(); aPI = new Retrofit.Builder() .client(mOkHttpClient) .baseUrl("服务器地址") .addConverterFactory(GsonConverterFactory.create())//指定json处理库 .build().create(API.class); //将第一步创建的API接口传入 } } } return aPI; }

3.开始发送请求
Call = call = RetrofitService.getInstance() .createShowAPI() .get("参数1", "参数2"); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { //请求成功的处理 }@Override public void onFailure(Call>> call, Throwable t) { //请求失败的处理 } });

Retrofit的核心-动态代理 Retrofit是如何将我们定义的接口方法最后转化成请求发送出去呢,这里就到源码去看看
创建者模式
首先来看Retrofit的创建,这里使用了创建者模式
new Retrofit.Builder() .client(mOkHttpClient) .baseUrl("服务器地址") .addConverterFactory(GsonConverterFactory.create())//指定json处理库 .build().create(API.class); //将第一步创建的API接口传入

首先来看Retrofit.Builder()这个类的构造方法
public static final class Builder { public Builder() { this(Platform.get()); } }

这里调用了一个带参数的构造方法,先看看Platform.get()是什么
private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; }

Platform.findPlatform
private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); }

可以看到,这个Platform类,顾名思义其实就是平台。在Retrofit中,内置了两种平台,一种是Android,一种是Java8。不同的平台,处理的方式不同。继续往下看代码就明白了
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); }@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); }static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } }

这里先不深入探究,后面还会再回来,不过我们已经可以看到,Executor类在Android平台里是返回了MainThreadExecutor,里面提供了一个handler,并且这个handler是传入的主线程的Looper,也就是说在execute方法里面,handler.post实际上是在主线程(UI线程)执行的。
这里再回到Retrofit.Builder(),看看那个带参数的构造方法:
public Builder() { this(Platform.get()); }Builder(Retrofit retrofit) { platform = Platform.get(); callFactory = retrofit.callFactory; baseUrl = retrofit.baseUrl; converterFactories.addAll(retrofit.converterFactories); adapterFactories.addAll(retrofit.adapterFactories); // Remove the default, platform-aware call adapter added by build(). adapterFactories.remove(adapterFactories.size() - 1); callbackExecutor = retrofit.callbackExecutor; validateEagerly = retrofit.validateEagerly; }

在这个构造方法里,对各种属性进行了初始化,来看看这些属性的定义
private final Platform platform; //刚才看到的平台,这里是Android private @Nullable okhttp3.Call.Factory callFactory; //后面在分析 private HttpUrl baseUrl; //服务器地址 private final List converterFactories = new ArrayList<>(); //json解析工厂列表 private final List adapterFactories = new ArrayList<>(); //后面再分析 private @Nullable Executor callbackExecutor; //这里是Android的Executor,在主线程执行回调 private boolean validateEagerly; //是否提前创建的标志

挨个看看这几个属性,这里有些属性的作用我们后面才知道,不过大部分看命名已经可以看到一些蹊跷:主要是callFactory和adapterFactories我们现在暂时不知道作用,继续往下看,在构造方法初始化之后,是调用Builder.build()方法
Builder.build()
public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); }okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); }Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); }// Make a defensive copy of the adapters and add the default Call adapter. List adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); } }

在这里是将Builder的属性,再传给Retrofit的构造方法,来看看我们刚才疑惑的那两个属性怎么赋值:
callFactory
okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); }

callFactory在默认的情况下,其实是一个OkHttpClient,也就是说Retrofit的内部请求原理其实是用的OkHttp。还记得我们最开始创建的时候也传入了一个静态类OkHttpClient么,这之间有什么关系呢?
new Retrofit.Builder().client(mOkHttpClient)

Retrofit.Builder().client
public Builder client(OkHttpClient client) { return callFactory(checkNotNull(client, "client == null")); }public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; }

其实client里面传入的OkHttpClient也是赋值给了callFactory,所以callFactory就是OkHttp的网络请求客户端
adapterFactories
// Make a defensive copy of the adapters and add the default Call adapter. List adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

创建了一个新的列表,并且加入了默认的CallAdapterFactory,刚才我们知道platform是Android,所以再看看之前的代码:
Platform.Android
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); }@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); }static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } }

defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory { final Executor callbackExecutor; ExecutorCallAdapterFactory(Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } }

可以看到构造方法并没有做什么,只是将回调处理类传入。里面的其他方法后面调用的时候再来看。所以到这里我们还是不知道adapterFactories是干嘛的,但是我们看到了这个类里面有enqueue方法,还有一些处理响应的一些方法,所以我们可以知道它的作用是处理请求和响应,具体的用法后面继续看源码可以看到。
Retrofit.creat
在创建者初始化了所有属性之后,来到了Retrofit.creat方法
aPI = new Retrofit.Builder() .client(mOkHttpClient) .baseUrl("服务器地址") .addConverterFactory(GsonConverterFactory.create())//指定json处理库 .build().create(API.class);

Retrofit.creat
public T create(final Class service) { Utils.validateServiceInterface(service); //验证是否传入的为接口类 if (validateEagerly) {//提前创建,默认为false,这里跳过 eagerlyValidateMethods(service); } return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // 方法定义所在的类,这里我们是定义在接口里面,返回false if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } //platform.isDefaultMethod没做任何处理,直接返回false if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod serviceMethod = (ServiceMethod) loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
这里看到了Retrofit的核心,使用动态代理来处理我们在接口中定义的方法。在调用我们定义的接口方法时,会来到动态代理类的invoke方法,然后执行最后的三行,在这里会解析定义的接口方法,并且做相应的处理。
总结 Retrofit在创建的过程中,有这么一些东西需要我们注意
platform 这个是Retrofit支持的平台,里面有Android和Java8,这里自然是Android
callFactory 执行请求的客户端,这里是OkHttpClient,在创建的时候.client传入
converterFactories json解析处理工厂数组,这里是GsonConverterFactory。进行请求和响应的解析,将json字符串转换为具体的实体类
callAdapterFactories 请求和响应的具体处理适配器工厂数组,这里没有传的话默认为ExecutorCallAdapterFactory,如果需要使用rxjava,为RxJava2CallAdapterFactory
callbackExecutor 【第三方库探究|Retrofit是如何创建的(为什么要用动态代理)】回调处理类,用于对回调数据的处理,这里是Android平台默认的MainThreadExecutor,使用Handler在主线程中处理回调。
第三方库探究|Retrofit是如何创建的(为什么要用动态代理)
文章图片
聊技术 聊电影 聊人生 什么都聊的公众号

    推荐阅读