Retrofit源码解析(下)

2023-05-19,,

接着上一章继续分析上一章主要简单说了一下基本使用和注解,这一章,我们主要看源码,废话不多说了,直接上。先上一张图 从网络上拿来的

前面一章说了一下Retrofit的简单使用https://www.cnblogs.com/huangjialin/p/9492182.html

     //创建retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url) //设置baseURl
.addConverterFactory(ScalarsConverterFactory.create()) //增加返回值为String的支持
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService apiService = retrofit.create(ApiService.class);
Call<SwitchTest> call = apiService.getInformation();
call.enqueue(new Callback<SwitchTest>() {
@Override
public void onResponse(Call<SwitchTest> call, Response<SwitchTest> response) {
Log.d("huangjialin", "---onResponse----" + response.body().getMessage());
} @Override
public void onFailure(Call<SwitchTest> call, Throwable t) {
Log.d("huangjialin", "--- 失败----" ); }
});

我们看一下new Retrofit.Builder()源码是怎么走的

 public Builder() {
this(Platform.get());
}
 class Platform {
private static final Platform PLATFORM = findPlatform(); static Platform get() {
return PLATFORM;
} private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != ) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
//—————省略若干代码—————-
}

从代码中可以看出来,Builder后先是调用this(Platform.get());然后在调用findPlatform()方法,在findPlatform()方法中主要进行平台的判断,不同的平台返回不同的线程池。在最新的几个版本中去掉了iOS平台的判断。
好了,回过头来我们接着看build()方法是怎么执行的

 public Retrofit build() {
if (baseUrl == null) { //从这里这里知道baseUrl一定不能为空,也就是说必须要设置,否则会抛异常
throw new IllegalStateException("Base URL required.");
} okhttp3.Call.Factory callFactory = this.callFactory; //如果需要对OkHttpClient进行设置,则可以构建OkHttpClient对象,然后调用callFactory方法将设置好的OkHttpClient传进去。
if (callFactory == null) {
callFactory = new OkHttpClient();
} Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor(); //将回调传递到主线程
} // adapterFactories主要用于存储对Call进行转化的对象
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); //主要用于存储数据转换后的对象
List<Converter.Factory> converterFactories =
new ArrayList<>( + 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); //将retrofit对象返回来
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

上面做的注释很清晰,也就是说build()后,我们可以拿到这个Retrofit这个对象,接着ApiService apiService = retrofit.create(ApiService.class);我们看看这句代码的源码是怎么走的

 public <T> T create(final Class<T> service) {
//这里主要是进行一些判断验证,比如说我们这里定义的ApiService,这个只能定义为interfaces类型,而不能定义为class类型。并且interfaces不能被扩展
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 (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//判断是否在主线程
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}

当进行一系列验证判断以后,Proxy.newProxyInstance来拿到一个动态代理,同时实现invoke()方法。通过当我们调用接口中的方法时,比如说调用登陆接口 Call<LoginModel> login(@Body Login login);,
这个时候就会调用InvocationHandler中的invoke方法,invoke()方法中有三个参数,第一个就是代理对象,第二个就是所调用的方法,比如说调用登陆接口,这个方法就是login,第三个就是方法参数了。
接着我们找到loadServiceMethod(method)我们看看是怎么执行的。

 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;
}

loadServiceMethod这个方法,首先进行一下判断,也就是说先从缓存中获取,看看缓存中有没有这个请求方法,如果有的话,那就直接返回,没有的话,通过new ServiceMethod.Builder<>(this, method).build();
来构建,然后在保存起来。我们看看build()中的源码

  public ServiceMethod build() {
//调用了createCallAdapter方法,它最终会得到我们在构建Retrofit调用build方法时adapterFactories添加的对象的get方法
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?");
}
//这里面通过遍历来拿到我们适合的Converter的转化对象,由于retrofit可以调用addConverterFactory添加多个,如Gson
responseConverter = createResponseConverter(); //这里主要是通过遍历拿到请求请求方法,如GET POST ,PUT这些
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);
} //这里获取到我们接口上面的参数注解比如说@Query @QueryMap这些
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.");
} //返回ServiceMethod对象
return new ServiceMethod<>(this);
}

上面这个方法主要目的就是为了拿到ServiceMethod对象。回过头来,我们继续看retrofit的create()方法

 ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

当拿到serviceMethod对象以后,接着就执行new OkHttpCall();来得到okHttpCall,并且最后返回serviceMethod.adapt(okHttpCall),我们进入OkHttpCall()对象看看

 final class OkHttpCall<T> implements Call<T> {

   //------省略若干代码--------

   @Override public synchronized Request request() {
okhttp3.Call call = rawCall;
if (call != null) {
return call.request();
}
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw new RuntimeException("Unable to create request.", creationFailure);
} else if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
try {
return (rawCall = createRawCall()).request();
} catch (RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
} catch (IOException e) {
creationFailure = e;
throw new RuntimeException("Unable to create request.", e);
}
} @Override public void enqueue(final Callback<T> 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<T> 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接口,然后通过request()和enqueue()这两个方法,然后将请求的结果回调回来,从而实现网络通信。
当然,这里只是retrofit一些基本的流程在源码中是这样走的,如果说要非常非常详细的源码,这不是一两篇文章能写完的,光retrofit就可以写出一本书了,当然,目前的水平,还没有达到那个地步,慢慢来。

Retrofit源码解析(下)的相关教程结束。

《Retrofit源码解析(下).doc》

下载本文的Word格式文档,以方便收藏与打印。