Android(安卓)Retrofit 源码系列(一)~ 原理剖析
Retrofit 系列文章导读:
- Android Retrofit 源码系列(一)~ 原理剖析
- Android Retrofit 源码系列(二)~ 自定义 CallAdapter
- Android Retrofit 源码系列(三)~ 整合 RxJava、Coroutine 分析
- Android Retrofit 源码系列(四)~ 文件上传
- Android Retrofit 源码系列(五)~ 设计模式分析
概述
我们知道 Retrofit 网络框架在 Android 开发中的使用是非常普遍的,而且可以很方便的和 RxJava、Kotlin Coroutine
结合使用。
最近花了一些时间研究了一下 Retrofit 框架,从框架的使用到其实现原理研究了一遍,也有一些心得体会。所以决定通过博客的方式将其分享出来,算是对这段时间研究 Retrofit 的归纳和总结,同时希望对大家有帮助。
关于 Retrofit 框架的文章预计会有好几篇,文章的特点如下:
-
文章的组织方式不会一头扎进源码分析一通,而是先从使用案例入手,然后分析其实现原理。
-
Retrofit 是一个网络框架,那么最好是有一个服务端与之对应,这样才能更好的对网络请求进行调试。所以我搭建了一个 Tomcat + Servlet 服务器用来接收网络请求,在调试 Retrofit 框架的时候产生的问题,我将会通过分析源码的方式来解答。
-
分析源码的一个直接好处是知道其实现原理。除此以外呢?开源框架这么多,我们能不能提取、总结一些通用的东西出来,提高我们的代码水平。我将在本系列文章的最后一篇文章中汇总一下对 Retrofit 源代码分析的体会。
本文基于的 Retrofit2 的版本是 2.7.0
从简单的案例入手
Retrofit 的使用是非常简单的,看一下官方文档基本上就能上手了。所以本文不会介绍 Retrofit 每个注解的使用,如果对 Retrofit 不熟的,可以花几分钟的时间在 retrofit官网 上了解下。
下面我们来看一个简单的案例:
// 定义网络接口类interface UserService {@POST("register")@FormUrlEncodedfun register(@Field("username") username: String,@Field("mobile") mobile: String): Call>}private val userService by lazy {// 构建 Retrofit 实例val retrofit: Retrofit = Retrofit.Builder().baseUrl(API_URL).addConverterFactory(GsonConverterFactory.create()).build()// 创建网络接口的实现类retrofit.create(UserService::class.java)}private fun request() {// 调用业务方法,返回一个 Call 对象val call = userService.register("chiclaim", "110")showLoading()// 执行网络请求call.enqueue(object : retrofit2.Callback> {// 网络请求失败回调override fun onFailure(call: Call>, t: Throwable) {dismissLoading()ToastHelper.showToast(applicationContext, t.message)text_content.text = t.message}// 网络请求成功回调override fun onResponse(call: Call>, response: Response>) {dismissLoading()val repsModel = response.body()val code = response.code()if (code in 200..299) {text_content.text = (repsModel?.message)text_content.append("\n")text_content.append(repsModel?.data.toString())} else {text_content.text = "response code ${response.code()}\n${repsModel?.message}"}}})}
上面的案例非常简单,和官网的介绍大同小异,只不过是自己写了一个简单的后端程序来对接这个请求而已。
但是我们不能仅仅满足于 API 调用,我们还应该去了解其背后的实现原理。下面我将对该案例,抛出几个问题,然后通过分析源码的方式找到问题的答案。
抛出问题
针对上面的案例,我抛出了如下几个问题:
-
我们只是定义了接口(UserService),并没有定义实现类,Retrofit 如何产生实现类的?
-
在没有使用 Retrofit 之前,发送网络请求,我们需要自己组装参数,Retrofit 如何通过注解组装请求参数的?
-
ConverterFactory 有什么用?它在哪个环节起作用的?
从源码中找到答案
上面的案例中的 retrofit.create()
方法就是用来创建业务实现类的:
retrofit.create(UserService::class.java)
然后我们看下 create 方法的具体实现:
public T create(final Class service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; @Override public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // 如果调用的方法是 Object 方法,则普通调用即可 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); }// 如果调用的方法是 interface default 方法(JDK1.8) if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); }// 如果调用的是我们定义的业务方法 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } });}
发现它是使用动态代理实现的,所以第一步是要理解动态代理的基本原理。关于动态代理的作用和基本原理,我以前分析代理模式的时候阐述过,需要的可以移步《设计模式 ~ 深入理解代理模式》
所以对于第一个问题:“我们只是定义了接口(UserService),并没有定义实现类,Retrofit 如何产生实现类的?” 就很好回答了,Retrofit 通过动态代理的方式来实现的。
接下来就要分析 Retrofit 动态代理的具体实现了。在调用具体的业务方法的时候,如:
val call = userService.register("chiclaim", "110")
最终会调用到 InvocationHandler.invoke
方法,上面我已经在 invoke
方法中主要逻辑加上了注释说明。核心的代码逻辑就是:
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
那来看下 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 = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result;}
里面主要逻辑是解析方法注解,封装成 ServiceMethod
,然后放在 serviceMethodCache
缓存容器中。loadServiceMethod
方法的主要逻辑在 parseAnnotations
方法里:
static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
ServiceMethod.parseAnnotations
方法里主要是两个方法:
- RequestFactory.parseAnnotations
- HttpServiceMethod.parseAnnotations
我们先来看下 RequestFactory.parseAnnotations
方法:
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build();} RequestFactory build() { // 解析方法上的注解,如 @GET、@POST、@Multipart、@FormUrlEncoded for (Annotation annotation : methodAnnotations) {parseMethodAnnotation(annotation); } // 省略参数的校验... int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; // 将参数注解转化成 ParameterHandler // 所有的参数注解都有一个类与之对应,并且该类继承了 ParameterHandler // 这些类都是 ParameterHandler 的内部类 // ParameterHandler 核心方法是 apply,用于将方法上的参数值添加到 RequestBuilder 当中 for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {parameterHandlers[p] =parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } // 省略参数的校验... return new RequestFactory(this);}
RequestFactory.parseAnnotations
方法主要是将解析接口方法参数注解,封装在 RequestFactory 对象中,然后将其返回。
这样我们就回答了第二个问题:Retrofit 如何通过注解组装请求参数的? 主要是通过 RequestFactory.parseAnnotations
解析方法上的注解。
RequestFactory
主要用于在后面创建 OkHttp 发起请求所需要的 Request 对象,这个后面会分析到。
我们继续来看下 HttpServiceMethod.parseAnnotations
方法:
static HttpServiceMethod parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; boolean continuationWantsResponse = false; boolean continuationBodyNullable = false; Annotation[] annotations = method.getAnnotations(); Type adapterType; if (isKotlinSuspendFunction) { Type[] parameterTypes = method.getGenericParameterTypes(); Type responseType = Utils.getParameterLowerBound(0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]); if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { // Unwrap the actual body type from Response. responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); continuationWantsResponse = true; } else { // 省略注释... } adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); }// 创建 CallAdapter,后面会详细分析 CallAdapter 类 CallAdapter callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); // 省略参数校验...// 创建 responseConverter 用于将请求的返回结果,转换成需要的对象 Converter responseConverter = createResponseConverter(retrofit, method, responseType);// callFactory 是在 Retrofit.build 的时候默认设置进去的 OkHttpClient,用于执行网络请求 okhttp3.Call.Factory callFactory = retrofit.callFactory;// 如果不是 kotlin suspend 函数 if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); }// 如果是 kotlin suspend 函数,且函数的返回类型是 Response,例如:// suspend fun register( // @Field("username") username: String, // @Field("mobile") mobile: String): Response// 这里的 register 方法就会本逻辑else if (continuationWantsResponse) { return (HttpServiceMethod) new SuspendForResponse<>(requestFactory, callFactory, responseConverter, (CallAdapter>) callAdapter); }// 其他情况。例如 suspend 函数,返回结果是 Body Data,而不是 Response,例如: // suspend fun register( // @Field("username") username: String, // @Field("mobile") mobile: String): Userelse { return (HttpServiceMethod) new SuspendForBody<>(requestFactory, callFactory, responseConverter, (CallAdapter>) callAdapter, continuationBodyNullable); } }
这样我们就将 ServiceMethod.parseAnnotations
方法里的:RequestFactory.parseAnnotations
和 HttpServiceMethod.parseAnnotations
分析完毕了。
由于 loadServiceMethod
的主要逻辑是 ServiceMethod.parseAnnotations
,所以 loadServiceMethod
也着分析完毕了。所以接下来就要分析下 invoke
方法:
// 动态代理里的核心逻辑(这里在贴一下)loadServiceMethod(method).invoke(args != null ? args : emptyArgs);abstract class HttpServiceMethod {@Override final @Nullable ReturnT invoke(Object[] args) {Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);return adapt(call, args);}// adapt 方法是一个抽象方法,具体使用哪个子类的实现取决于接口函数的使用方式,我们已经在 HttpServiceMethod.parseAnnotations 分析过了// 如果接口函数不是 kotlin suspend 则使用 CallAdapted 类// 如果是 kotlin suspend 函数返回类型是 Response,则使用 SuspendForResponse 类// 接口函数为其他情况如:kotlin suspend 函数返回类型不是 Response,则使用 SuspendForBody 类// 以上 3 个类都是 HttpServiceMethod 的子类protected abstract @Nullable ReturnT adapt(Call call, Object[] args);}
下面我们就来分析下 HttpServiceMethod
的三个子类:
- CallAdapted
- SuspendForResponse
- SuspendForBody
不管是哪个子类,它们的构造方法都依赖 ResponseConverter、CallAdapter(注意不是 CallAdapted)
所以我们先来分析下 ResponseConverter 的创建过程:
val retrofit = Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build()
我们是通过 addConverterFactory
方法将 GsonConverterFactory
转化器工厂加进去的, GsonConverterFactory
创建的是 GsonResponseBodyConverter
:
final class GsonResponseBodyConverter implements Converter { private final Gson gson; private final TypeAdapter adapter; GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return result; } finally { value.close(); } }}
GsonResponseBodyConverter 简而言之就是将响应体里的数据通过 GSON 转化成我们所需要的对象
然后我们在来看 CallAdapter,实际上 CallAdapter 对象是在 HttpServiceMethod.parseAnnotations
方法创建的:
class HttpServiceMethod {static HttpServiceMethod parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) {// 创建 CallAdapterCallAdapter callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);// 省略其他代码...}// createCallAdapterprivate static CallAdapter createCallAdapter( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {try { // 调用了 Retrofit.callAdapter return (CallAdapter) retrofit.callAdapter(returnType, annotations);} catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create call adapter for %s", returnType);}}}public final class Retrofit {public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {return nextCallAdapter(null, returnType, annotations);} // 我们再来看下 nextCallAdapterpublic CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { // 省略参数校验... // 由于上传传递进来的参数 skipPast 是 null,所以 start 就等于 0int start = callAdapterFactories.indexOf(skipPast) + 1;for (int i = start, count = callAdapterFactories.size(); i < count; i++) { // 从 callAdapterFactories 工厂集合中获取工厂,并且创建 CallAdapter CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) {return adapter; }}// 省略组装错误信息...throw new IllegalArgumentException(builder.toString());}}
从 callAdapterFactories
工厂集合中获取工厂,并且创建 CallAdapter
。但是我们文章开头的案例中并没有添加 CallAdapterFactory
,我们只是添加了 ConverterFactory
:
val retrofit: Retrofit = Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .build()
其实是在 build 方法中添加默认的 CallAdapterFactory:
public Retrofit build() { // 省略其他逻辑... // 创建 CallAdapter 工厂集合 List callAdapterFactories = new ArrayList<>(this.callAdapterFactories); // 添加默认的 CallAdapterFactory callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);}
我们在来看下 Platform.defaultCallAdapterFactories
:
class Platform { List<? extends CallAdapter.Factory> defaultCallAdapterFactories( @Nullable Executor callbackExecutor) {// 创建 DefaultCallAdapterFactory DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor); return hasJava8Types ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory) : singletonList(executorFactory); } }
然后我们看下 DefaultCallAdapterFactory
工厂是怎么创建 CallAdapter
的:
final class DefaultCallAdapterFactory extends CallAdapter.Factory { private final @Nullable Executor callbackExecutor; DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) { this.callbackExecutor = callbackExecutor; } // 创建 CallAdapter @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { // 省略参数校验... final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);// 如果接口方法使用了 @SkipCallbackExecutor 注解,则不使用 callbackExecutor final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor;// 返回 CallAdapter 匿名内部类对象 return new CallAdapter
至此,怎么创建 AdapterFactory
就搞清楚了。
这个时候可以来介绍 HttpServiceMethod
的三个子类了(CallAdapted、SuspendForResponse、SuspendForBody)
经过上面的分析我们知道,当我们接口方法不是 suspend 方法时,如:
@POST("users/new") fun createUser(@Body user: User): Call
HttpServiceMethod.parseAnnotations
将会返回 CallAdapted
:
static final class CallAdapted extends HttpServiceMethod { private final CallAdapter callAdapter; // 省略构造方法... @Override protected ReturnT adapt(Call call, Object[] args) { return callAdapter.adapt(call); } }
发现里面非常简单,就是直接调用 callAdapter.adapt 方法而已。
如果是我们的接口函数是 kotlin suspend 函数,且函数的返回类型是 Response,例如:
suspend fun register( @Field("username") username: String, @Field("mobile") mobile: String): Response
HttpServiceMethod.parseAnnotations
将会返回 SuspendForResponse
,SuspendForResponse 要比 CallAdapted,稍微复杂一点:
static final class SuspendForResponse extends HttpServiceMethod {private final CallAdapter> callAdapter;// 省略构造方法...@Override protected Object adapt(Call call, Object[] args) { call = callAdapter.adapt(call); Continuation> continuation = (Continuation>) args[args.length - 1]; try {return KotlinExtensions.awaitResponse(call, continuation); } catch (Exception e) {return KotlinExtensions.suspendAndThrow(e, continuation); }}}suspend fun Call.awaitResponse(): Response { return suspendCancellableCoroutine { continuation ->// 协程取消掉的时候,调用 Call.cancel() continuation.invokeOnCancellation { cancel() }// 调用 Call.enenque,真正开始执行网络请求任务 enqueue(object : Callback { override fun onResponse(call: Call, response: Response) {// 继续执行相应的协程,将 response 作为最后一个挂起点的返回值 continuation.resume(response) } override fun onFailure(call: Call, t: Throwable) { continuation.resumeWithException(t) } }) }}
如果接口函数是 kotlin suspend 函数,但是函数的返回值不是 Response,如:
suspend fun register( @Field("username") username: String, @Field("mobile") mobile: String): User
HttpServiceMethod.parseAnnotations
将会返回 SuspendForBody
,它和 SuspendForResponse 差别在于 SuspendForBody 将 Response.body
作为协程挂起点的返回值:
static final class SuspendForBody extends HttpServiceMethod { private final CallAdapter> callAdapter; private final boolean isNullable;// 省略构造方法... @Override protected Object adapt(Call call, Object[] args) { call = callAdapter.adapt(call); Continuation continuation = (Continuation) args[args.length - 1]; try { return isNullable ? KotlinExtensions.awaitNullable(call, continuation) : KotlinExtensions.await(call, continuation); } catch (Exception e) { return KotlinExtensions.suspendAndThrow(e, continuation); } }}// awaitNullable 方法@JvmName("awaitNullable")suspend fun Call.await(): T? { return suspendCancellableCoroutine { continuation ->// 协程取消掉的时候,调用 Call.cancel() continuation.invokeOnCancellation { cancel() }// 调用 Call.enenque,真正开始执行网络请求任务 enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { // 继续执行相应的协程,将 response.body 作为最后一个挂起点的返回值 continuation.resume(response.body()) } else { continuation.resumeWithException(HttpException(response)) } } override fun onFailure(call: Call, t: Throwable) { continuation.resumeWithException(t) } }) }}
不管是 CallAdapted、SuspendForResponse、SuspendForBody,它们的 adapt 方法都依赖 OkHttpCall
:
@Override final @Nullable ReturnT invoke(Object[] args) { Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args);}
从名字上可以看出最终的请求是通过 OkHttp 来执行最终的网络请求,我们来看下 OkHttpCall:
final class OkHttpCall implements Call { // 省略成员变量... // 由于篇幅原因,只保留同步请求和异步请求... // 异步请求 @Override public void enqueue(final Callback callback) { 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 { // 里面的实现相当于 OkHttpClient.newCall call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } }// 省略其他代码...// 通过 OkHttp 发起异步网络请求... call.enqueue(new okhttp3.Callback() { // 处理请求结果 @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response response; try { // 将 OkHttp Response 转化成 Retrofit Response response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { // 成功回调 callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { throwIfFatal(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) { throwIfFatal(t); t.printStackTrace(); } } }); } // 同步请求 @Override public Response execute() throws IOException { okhttp3.Call call; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; // 省略异常抛出... call = rawCall; if (call == null) { try { // 里面的实现相当于 OkHttpClient.newCall call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); creationFailure = e; throw e; } } } if (canceled) { call.cancel(); }// 将 OkHttp Response 转化成 Retrofit Response return parseResponse(call.execute()); } private okhttp3.Call createRawCall() throws IOException {// 这里的 callFactory 默认是 OkHttpClient// requestFactory.create 用于创建 OkHttp 发起网络请求所需要的 Request 对象 okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } // 解析 OkHttp Response,将其转化成 Retrofit Response Response parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); // Remove the body's source (the only stateful object) so we can pass the response along. rawResponse = rawResponse.newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code();// HTTP code 非成功状态 if (code < 200 || code >= 300) { try { ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } }// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/204// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/205// HTTP 204 表示该请求已经成功了,但是客户端客户不需要离开当前页面。默认情况下 204 响应是可缓存的。一个 ETag 标头包含在此类响应中// HTTP 205 表示该请求已经成功了,用来通知客户端重置文档视图// 204、205 Response.body 设置为 null,所以上层需要注意 body 为 null 的情况 if (code == 204 || code == 205) { rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { // 这里的 responseConverter 实际上就是 GsonResponseBodyConverter // 这是在 build Retrofit 对象的时候设置的: // val retrofit: Retrofit = Retrofit.Builder() // .baseUrl(API_URL) // .addConverterFactory(GsonConverterFactory.create()) // .build() // 将会返回结果转成需要的类型 T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }}
介绍完 OkHttpCall ,我们也就能回答第三个问题了:“ConverterFactory 有什么用?它在哪个环节起作用的?”
ConverterFactory
主要用于对象的序列化和反序列化,比如说将请求的对象转成 JSON ,然后传递给服务器,获取将服务器返回的 JSON 转成我们需要的对象。
例如 OkHttpCall.parseResponse
用到的 Converter 将服务器返回的 JSON 转成我们需要的对象。
除此以外,在 OkHttpCall.parseResponse
方法中我们还发现,如果 HTTP code 如果是 204 或者 205,Response 的 body 会是 null,所以在使用的 Retrofit 的时候就一定要注意 body 空的情况。比如:
@POST("register")@FormUrlEncodedfun registerByRxJava(@Field("username") username: String?,@Field("mobile") mobile: String): Observable?>
如果此时 HTTP code 是 204 或 205 ,虽然网络请求成功,但是会抛出空指针异常:
java.lang.NullPointerException: Null is not a valid element
这个我们将在介绍 Retrofit 结合 RxJava 使用的时候继续分析。
小结
至此,我们就以一个简单的案例为引子,将 Retrofit 是如何发起网络请求的整个过程以及 Retrofit 里的一些核心概念如 动态代理、CallAdapter、Converter 等都介绍完毕了。
本文涉及到的代码在我的 AndroidAll GitHub 仓库中。该仓库除了 Retrofit,还有Android 程序员需要掌握的技术栈,如:程序架构、设计模式、性能优化、数据结构算法、Kotlin、Flutter、NDK、Router、RxJava、Glide、LeakCanary、Dagger2、Retrofit、OkHttp、ButterKnife、Router 等等,持续更新,欢迎 star。
更多相关文章
- Android使背景灯(Brightness)高亮的方法
- 【Android】View绘制过程分析之draw
- android spinner自动弹出列表,设置title,TtextView不换行自动截取
- [置顶] Android系统安全之旅 第1章 编译Android程序的方法
- Android:捕捉触摸屏手势
- Android(安卓)的网络编程
- Android(安卓)发送短信 和 打电话 具体事项
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用