博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
拆轮子系列--Retrofit2源码分析
阅读量:6229 次
发布时间:2019-06-21

本文共 16048 字,大约阅读时间需要 53 分钟。

0.前言

Retrofit是一个基于okhttp的网络请求框架,相当于对于okhttp的一次封装,同理,也是square公司出的,square出品,必属精品,最近有时间,分析仪下它的工作流程,

1.基本使用

interface TestService    {        @GET("/")        fun test(): Call
} class ResponseConvertFactory : Converter.Factory() { override fun responseBodyConverter(type: Type?, annotations: Array
?, retrofit: Retrofit?): Converter
? { return Converter
{ it.string() } } override fun stringConverter(type: Type?, annotations: Array
?, retrofit: Retrofit?): Converter<*, String>? { return super.stringConverter(type, annotations, retrofit) } } val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com") .addConverterFactory(ResponseConvertFactory()) .build() val testService = retrofit.create(TestService::class.java) val call = testService.test() call.enqueue(object : Callback
{ override fun onFailure(call: Call
?, t: Throwable?) { } override fun onResponse(call: Call
?, response: Response
?) { println("response is ${response?.body()}") } }) 复制代码

这是一个简单的异步http get请求,由于只分析流程,由简单的进入就行了,个人认为看代码了解流程和其设计模式才是最重要的,不需要扣的太厉害。

2.Retrofit的创建

Retrofit的创建采用的建造者模式

val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com")                .addConverterFactory(ResponseConvertFactory())                .build()复制代码

直接看Retrofit.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
callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List
converterFactories = new ArrayList<>(1 + this.converterFactories.size()); // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }复制代码

这里传入了一个CallAdapter.Factory的list,里面的数据是Builder里的calladapter.Factory的list,也就是你在addCallAdapterFactory()方法中传入的参数,这里传入的factory会放入builder的calladapter.Factory的list里,然后又放入了一个默认的calladapterfactory,这个factory是platform的参数,而这个platform是在实例化Builder的时候传入的

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();  }复制代码

如果是跑在android系统,那么返回的就会是Android,看一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);      }    }  }复制代码

可以看到platform返回的CallAdapterFactory就是ExecutorCallAdapterFactory。关于他的作用稍后再谈。

还有一个Convert.Factory的list,这里是先加入了一个BuiltInConverters,然后放入存在Builder里的Convert.Factory的list,Convert.Factory主要是用来生成Convert来对http请求体和响应报文进行转换。

2.发行请求前的准备

val testService = retrofit.create(TestService::class.java)        val call = testService.test()复制代码

通过这两个方法,生成了一个实现TestService接口的实例,调用这个接口的方法返回一个Call。接下来就看看这是怎么做的,如何为接口生成了一个实例,还有怎么生成的Call。

public 
T create(final Class
service) { Utils.validateServiceInterface(service); if (validateEagerly) { 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 { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod
serviceMethod = (ServiceMethod
) loadServiceMethod(method); OkHttpCall
okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.adapt(okHttpCall); } }); }复制代码

well well,很明显,这是一个动态代理,如果对动态代理不清楚的,可以参考我之前的文章 。通过动态代理实现了一个实现接口的代理类,接下来看InvocationHandler,如果方法不是来自接口而是object的方法,那么就直接调用,如果是来自接口,那么可以看到先生成了一个serviceMethod,看一下loadServiceMethod方法

ServiceMethod
loadServiceMethod(Method method) { ServiceMethod
result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; }复制代码

很简单,如果缓存有,就取出一个ServiceMethod,否则就创建一个ServiceMethod,并添加到缓存,还是建造者模式,看一下ServiceMethod.Builder的build方法

public ServiceMethod build() {      callAdapter = createCallAdapter();      responseType = callAdapter.responseType();      if (responseType == Response.class || responseType == okhttp3.Response.class) {        throw methodError("'"            + Utils.getRawType(responseType).getName()            + "' is not a valid response body type. Did you mean ResponseBody?");      }      responseConverter = createResponseConverter();      for (Annotation annotation : methodAnnotations) {        parseMethodAnnotation(annotation);      }      if (httpMethod == null) {        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");      }      if (!hasBody) {        if (isMultipart) {          throw methodError(              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");        }        if (isFormEncoded) {          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "              + "request body (e.g., @POST).");        }      }      int parameterCount = parameterAnnotationsArray.length;      parameterHandlers = new ParameterHandler
[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } if (relativeUrl == null && !gotUrl) { throw methodError("Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError("Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError("Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError("Multipart method must contain at least one @Part."); } return new ServiceMethod<>(this); }复制代码

先看一下createCallAdapter这个方法

private CallAdapter
createCallAdapter() { Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError("Service methods cannot return void."); } Annotation[] annotations = method.getAnnotations(); try { //noinspection unchecked return (CallAdapter
) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } }复制代码

根据method返回值的Type和注解,调用retrofit的callAdapter返回Calladapter,看一下Retrofit的calladapter方法。

public CallAdapter
callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } public CallAdapter
nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter
adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } StringBuilder builder = new StringBuilder("Could not locate call adapter for ") .append(returnType) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }复制代码

言简意赅,遍历Retrofit的CallAdapterFactory list,找到符合要求的calladapter就返回,所以还记得calladapterfactory list的顺序吧,默认的calladapterfactory也就是ExecutorCallAdapterFactory是放在最后的,所以如果你在构建Retrofit的时候添加了别的Calladapter,如果符合条件,是会拦截。RxJavaCallAdapterFactory.create()这个眼熟吧,就是因为它最终返回的是Observable而不是Call。其实这个CallAdapter的作用就是讲OkhttpCall转化为其他数据结构,默认的就是将OkhttpCall转换为ExecutorCallbackCall。 再回到build方法

responseConverter = createResponseConverter();复制代码

和返回CallAdapter差不多,只不过这是返回的ResponseConvert 接下来

for (Annotation annotation : methodAnnotations) {        parseMethodAnnotation(annotation);      }复制代码

遍历方法注解得到相应参数,具体就不说了。

然后又生成了一个OkhttpCall

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);复制代码

你会发现这个OkhttpCall实现了OkHttp的call接口,看它的enque方法

@Override public void enqueue(final Callback
callback) { checkNotNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response
response; try { response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } @Override public void onFailure(okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } }); }复制代码

这里就是生成了一个Okhttp的call,然后接着就是okhttp的网络请求流程了,如果okhttp不熟悉可以看我之前的文章。

重新回到invaoctaionhandler,最后调用了serviceMethod.adapte方法,

T adapt(Call
call) { return callAdapter.adapt(call); }复制代码

可以看到就是调用了calladapter的adapt方法,前面说了默认的calladapter是ExecutorCallAdapterFactory制造的

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {  final Executor callbackExecutor;  ExecutorCallAdapterFactory(Executor callbackExecutor) {    this.callbackExecutor = callbackExecutor;  }  @Override  public CallAdapter
get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter
>() { @Override public Type responseType() { return responseType; } @Override public Call
adapt(Call call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } }; }复制代码

可以看到返回了一个匿名内部类,他的adapt方法实际返回了ExecutorCallbackCall

static final class ExecutorCallbackCall
implements Call
{ final Executor callbackExecutor; final Call
delegate; ExecutorCallbackCall(Executor callbackExecutor, Call
delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback
callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback
() { @Override public void onResponse(Call
call, final Response
response) { callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation. callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call
call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); } @Override public boolean isExecuted() { return delegate.isExecuted(); } @Override public Response
execute() throws IOException { return delegate.execute(); } @Override public void cancel() { delegate.cancel(); } @Override public boolean isCanceled() { return delegate.isCanceled(); } @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone. @Override public Call
clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); } @Override public Request request() { return delegate.request(); } }复制代码

可以发现这个也实现了Okhttp的call接口,同时还持有了一个callbackexecutor和之前生成的okhttpcall,可以发现调用它的enqueu方法真正执行网络请求的就是okhttpcall,而这个callbackexecutor实际是

static class MainThreadExecutor implements Executor {      private final Handler handler = new Handler(Looper.getMainLooper());      @Override public void execute(Runnable r) {        handler.post(r);      }    }复制代码

很明显,通过这种方式保证了回调结果在主线程。

(盗张图帮助理解)

关注我的公众号

转载地址:http://vjxna.baihongyu.com/

你可能感兴趣的文章
《paste命令》-linux命令五分钟系列之二十
查看>>
CTO职场解惑指南系列(一)
查看>>
安排!活动素材的亿级用户精准投放
查看>>
debian8.4下配置pgpool+pg9.5双主备
查看>>
用scrapy爬取ttlsa博文相关数据存储至mysql
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
AOP 的利器:ASM 3.0 介绍
查看>>
Redis数据结构详解,五种数据结构分分钟掌握
查看>>
解决Linux下编译.sh文件报错 “[: XXXX: unexpected operator”
查看>>
使用JConsole监控
查看>>
开发规范
查看>>
RAID技术
查看>>
excel 使用 navicat 导入数据库
查看>>
我的友情链接
查看>>
我的大学——我在科创协会的部长感悟
查看>>
数据结构之队列——顺序存储结构(php代码实现——方法一)
查看>>
Hive安装使用
查看>>
JDK 11的新特性
查看>>
MySQL优化20条经验(一)
查看>>