OkHttp3
由于其易于拓展、灵活配置同时缓存策略的通用性、连接复用的高性能,已经基本成为目前安卓开发者使用率最高的“基础网络框架”。
之所以强调“基础网络框架”,是因为现在市面上有许多基于 OkHttp3
再次封装的网络请求库,其中比较著名的是 Retrofit
。
Retrofit
独特的设计使得使用它发起网络请求就像服务端写接口一样,先定义一个 Service 然后直接调用方法即可,不用自己创建实现。
另外 Retrofit
可以和 Gson
RxJava
无缝结合,这让它的使用更加方便。
接下来我们将从 Retrofit
的使用例子出发,逐步深入地了解它方便使用的背后原理。
文章主要内容:
Retrofit 请求实现流程基本认识
Retrofit 如何拿到请求信息
Retrofit 如何转换请求、响应信息
Retrofit 请求实现流程基本认识
Retrofit
的使用非常简单,基本分四步:
定义接口、方法、参数、返回值
构造 Retrofit
调用 retrofit.create()
获取实例
调用方法获取返回值,执行接下来的异步或者同步请求
1.首先定义接口、方法、参数、返回值
public interface IApiService {
@GET("users/{user}/repos")
Call<List<String>> listRepos(@Path("user") String user);
@GET("users/{user}/repos")
Observable<List<String>> listReposObservable(@Path("user") String user);
}
复制代码
一般来说方法的返回值是 retrofit2.Call
,如果使用 RxJava 的话也可以是 Observable
。
在 OkHttp 中,Call
的唯一实现就是 RealCall
,它表示一个准备好被执行的请求;在 Retrofit 中也定义了一个 Call
接口,不过它俩的级别不一样,相较于 OkHttp.Call
,Retrofit.Call
增加了更多信息,这个我们后面介绍。
2.构造 Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
复制代码
构造 Retrofit
的参数不多,就这么几个:
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory; //默认是 OkHttpClient
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>(); //转换器
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); //适配器,将 Call 转换成指定的类型
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
//...
}
复制代码
其中 Converter
和 CallAdapter
是我们后面要关注的重点, ``Retrofit` 之所以灵活好用,离不开这两位大将。
3.调用 retrofit.create()
获取实例
retrofit.create(IApiService.class)
复制代码
这里用到了动态代理 Proxy.newProxyInstance()
,生成实例并且代理所有方法,当我们调用某个方法时,会调用这个代理的invoke()
方法,这也是 Retrofit
的重点,后面详细分析。
//Retrofit.create()
public <T> T create(final Class<T> 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 {
//...
}
});
}
复制代码
4.调用方法获取返回值,执行异步或者同步请求
retrofit.create(IApiService.class)
.listRepos("shixinzhang") //这里返回了 retrofit2.Call
.enqueue(new Callback<List<String>>() {
@Override
public void onResponse(Call<List<String>> call, Response<List<String>> response) {
List<String> body = response.body();
}
@Override
public void onFailure(Call<List<String>> call, Throwable t) {
}
});
复制代码
调用方法后之所以可以调用 enqueue()
方法,是因为我们在定义方法时返回值是 retrofit2.Call
。
retrofit2.Call
的实现类是 OkHttpCall
,它的成员属性有一个 okhttp3.Call
,发起请求就是通过 okhttp3.Call
来的:
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T, ?> serviceMethod;
private final @Nullable Object[] args;
private volatile boolean canceled;
private @Nullable okhttp3.Call rawCall;
private @Nullable Throwable creationFailure;
private boolean executed;
//...
}
复制代码
Retrofit
发起异步请求的实现:
//OkHttpCall.enqueue()
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
//...
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);
}
//...
});
}
复制代码
拿到响应后调用了 parseResponse()
方法,这个方法把 okhttp3.Response
转成了 Retrofit.Response
:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
//...
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody); //从响应里解析、转成指定的类型
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
throw e;
}
}
复制代码
可以看到,这个 parseResponse()
方法就是做了我们经常做的根据响应码判断,回调 success 或者 error 回调。
在方法的最后调用了 serviceMethod.toResponse()
将 okhttp3.Response
转换成指定的类型,具体的细节我们后面介绍。
OK,至此我们对 Retrofit
的发起请求到拿到响应有了基本的认识,用一张图概括一下:
接下来对一些核心细节进行深入学习。
上篇文章的的流程图中,我们有这些疑问:
接口的实现代理做了哪些额外操作?
接口中的信息是如何转换成请求信息?
拿到响应后是如何转换成指定的类型?
接下来我们一起来解决这些问题。
Retrofit 核心机制实现分析
接口的代理做了哪些操作
我们知道接口的动态代理实现是在 Retrofit.create()
方法中:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service); //验证是不是接口,有没有继承别的接口
if (validateEagerly) {
eagerlyValidateMethods(service); //预加载,默认 validateEagerly 是 false
}
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 {
//如果是 Object 的方法就直接调用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
复制代码
可以看到,这个 create()
方法首先验证了传入的 Class 是不是接口,然后为接口创建了代理实例。
以后调用这个实例的方法,都将经过这个匿名内部类 InvocationHandler
的 invoke()
方法。
我们知道任何类都会默认继承 Object
类,因此在 invoke()
方法中,遇到 Object
类的方法直接进行调用,不做任何处理。
然后就到了关键部分了:
//InvocationHandler.invoke()
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
//...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
复制代码
在这部分做了三件事:
调用 loadServiceMethod()
,参数是当前调用的方法,返回一个 ServiceMethod
实例
创建了一个 OkHttpCall
实例,参数是 serviceMethod
和当前调用方法传递的参数
调用了 serviceMethod.adapt(okHttpCall)
返回被代理方法的返回值
先来看看这个 ServiceMethod
是干什么的。
正如其名,一个 ServiceMethod
对象对应于一个接口的方法,它的职责是:把对接口方法的调用转为一次 HTTP 调用(敲黑板,这是重点)。
它的成员属性有很多:
private final okhttp3.Call.Factory callFactory;
private final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
复制代码
除了关于请求信息的,其中最重要的就是两个: CallAdapter
和 Converter<F, T>
。
CallAdapter
的作用是将我们在接口的方法中声明的返回值类型转成 retrofit2.Call
,如果我们直接声明方法的返回值就是 retrofit2.Call
, CallAdapter
就不需要做什么转换了,后面再详细介绍
Converter<F, T>
的作用是将用户的请求/响应类型 和 HTTP 的请求/响应类型进行转换,一般有两个,作用其实类似 OkHttp
的 BridgeInterceptor
回到 Retrofit.create()
中创建的代理的 invoke()
方法,先是调用了 loadServiceMethod()
方法返回一个 ServiceMethod
,我们看看这个方法做了什么:
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
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;
}
复制代码
可以看到,这个方法先去一个 Map 里根据 Method 方法对象去查询有没有之前保存的 ServiceMethod
,有就直接返回,没有就调用 ServiceMethod.Builder<>(this, method).build();
新建一个然后保存。
去瞅瞅这个 Builder:
//ServiceMethod.Builder
static final class Builder<T, R> {
final Retrofit retrofit;
//...
Converter<ResponseBody, T> responseConverter;
CallAdapter<T, R> callAdapter;
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
callAdapter = createCallAdapter(); //拿到可以处理当前接口方法的 ``CallAdapter``
responseType = callAdapter.responseType();
//...
responseConverter = createResponseConverter(); //拿到可以处理当前接口方法的 ``responseConverter``
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//...
return new ServiceMethod<>(this);
}
//...
}
复制代码
ServiceMethod.Builder
的 build()
方法中主要做了 3 件事:
实例化用于处理当前接口方法的 callAdapter
和 responseConverter
解析方法上的注解信息
来分别看看如何实现的。
前面提到:
因此不同的方法如果返回值不同, ServiceMethod
中的CallAdapter
是不同的。
我们来看看 ServiceMethod 是怎么找到能处理当前方法的 CallAdapter
:
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) { //首先判断返回值类型
throw methodError(//...);
}
if (returnType == void.class) {
throw methodError("//...");
}
Annotation[] annotations = method.getAnnotations();
try {
//调用 retrofit 的方法
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) {
//...
}
}
复制代码
如果你记不住 CallAdapter
是干嘛的,看到上面这个方法的前两个判断或许就能记住了,它是要处理返回值的,所以在创建前需要检查方法的返回值是否合理。
最后调用了 retrofit.callAdapter(returnType, annotations);
:
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;
//遍历 Retrofit 创建时添加的 callAdapterFactory
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//...
throw new IllegalArgumentException(builder.toString());
}
复制代码
可以看到,最后找适用于当前方法的 CallAdapter
是通过遍历 Retrofit
创建时添加的 CallAdapter.Factory
,然后调用每一个 factory 的 get() 方法,如果不为空表示能处理,就返回这个 CallAdapter
。
Retrofit
中我们主要用到两个 CallAdapterFactory
:
DefaultCallAdapterFactory
处理 Retrofit
默认返回值 Call<T>
的
RxJavaCallAdapterFactory
处理返回值为 Observable<T>
的
我们来简单看看 DefaultCallAdapterFactory.get()
方法:
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
//...
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) { //用于处理返回值是 Call
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() { //创建一个 CallAdapter,直接返回 Call
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return call;
}
};
}
}
复制代码
可以看到,默认的这个 DefaultCallAdapterFactory
只能处理返回值是 Call
,它返回的 CallAdapter
没有做额外工作,直接返回了这个返回值。
** ServiceMethod 寻找能处理当前方法的 Converter
的逻辑也是类似,去 Retrofit 的 converterFactory
列表里遍历寻找: **
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
//...
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
return (Converter<ResponseBody, T>) converter;
}
}
//...
throw new IllegalArgumentException(builder.toString());
}
复制代码
小结一下:创建一个 ServiceMethod
是要给它找能处理当前返回值的 CallAdapter
,它是通过去 Retrofit
的CallAdapter.Factory
列表(final List<CallAdapter.Factory> callAdapterFactories;
)里挨个调用 get()
方法来寻找的,找 responseConverter
响应转换器也是一样的。
OK,ServiceMethod
的前两步我们都了解了,最后看一下如何解析方法上的注解信息。
//ServiceMethod.Builder.build()
public ServiceMethod build() {
//...
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//...
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
//...
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
复制代码
可以看到解析方法上的注解信息主要分两步:
遍历方法上的所有注解 methodAnnotations
解析请求方法和地址
遍历参数中的所有注解 parameterAnnotationsArray
解析参数,比如相对路径、查询值,解析结果保存到 ParameterHandler
中
具体代码比较简单,这里就不再赘述了。
了解了 ServiceMethod
的创建后,代理方法的第二步是创建了一个 OkHttpCall
,前面介绍请求流程时已经介绍过, OkHttpCall
就是对 okhttp3.Call
的封装,它的同步异步请求都是通过调用 okhttp3.Call
的方法实现的。
调用 okhttp3.Call
需要传递 okhttp.Request
请求信息,这里的请求信息就是通过持有前面创建的 ServiceMethod
来实现的。
在调用 OkHttpCall
的同步、异步请求时,会先调用 OkHttpCall.createRawCall()
方法创建一个 okhttp3.Call
:
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
复制代码
可以看到是调用的 ServiceMethod
的 toCall()
方法创建的,这个 ServiceMethod
太关键了,一定要记住它。
//ServiceMethod.toCall()
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
//...
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return callFactory.newCall(requestBuilder.build());
}
复制代码
可以看到,这个方法就是把前面解析注解拿到的数据都组装起来,创建一个 Request
传递给 OkHttpClient
。
前两步清楚了,最后看第三步 serviceMethod.adapt(okHttpCall)
:
//ServiceMethod.adapt()
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
复制代码
我们知道当返回值类型是 Call
时 CallAdapter
的不做任何操作,也就是做,调用这个 ServiceMethod.adapt()
方法的作用就是返回上一步创建的 OkHttpCall
。
当我们使用 RxJava 时返回值是 Observable
,这时的 CallAdapter
的作用就是将 Observable
转换成 OkHttpCall
。
OK,至此我们对代理做了什么算是彻底了解了,总结一下:
解析注解,创建能处理当前方法的 CallAdapter
和 Converter
创建封装底层 okhttp3.Call
的 OkHttpCall
,这个类在执行网络请求时,会根据之前创建的 ServiceMethod
来组装请求信息
将方法的返回值转换成要做请求的 OkHttpCall
,当返回值是 Call
时就不做任何处理
如果有使用 retrofit2.http.Body
修饰的参数,这个对象会被某一个 Converter.Factory
实例转换成 OkHttp
请求体(okhttp3.RequestBody
)
Converter<F, T>的作用是将用户的请求/响应类型 和 HTTP 的请求/响应类型进行转换,一般有两个,作用其实类似
OkHttp的
BridgeInterceptor``
Retrofit 如何拿到请求信息
我们使用 Retrofit
时只要定义接口和方法,然后使用注解表示请求方法、请求参数以及输入返回值即可。
那它进行网络请求时是如何拿到请求信息的呢?
上一节中介绍代理拦截方法时做的工作时,我们已经得到了答案:
Retrofit.create()
方法为接口创建动态代理
当调用接口的方法时,会调用拦截的 invoke()
方法
在这个方法里先是创建了 ServiceMethod
(它可以解析方法上的注解和参数的注解,同时寻找能处理当前方法的 CallAdapter
和 Converter
)
然后创建了封装底层请求的 OkHttpCall
,这个类会在做请求时,根据 ServiceMethod
的信息创建一个 okhttp3.Request
,从而创建一个 okhttp3.Call
做网络请求
Retrofit 如何转换请求、响应信息
经过前面的学习我们知道,Retrofit
中 Converter
就是负责转换 请求、响应信息 的。它一般有两种:
将使用 @Body
修饰的参数转换成请求体
将网络响应的响应体 ResponseBody
转换成用户指定的类型
先看如何实现将使用 @Body
修饰的参数转换成请求体。
我们使用 Retrofit
做 POST
请求时,可以使用 @Body
注解修饰一个实体,它表示要提交的请求体:
public interface IApiService {
@POST("users//repos/update")
Call<List<Result>> updateRepos(@Body RepoInfo repoInfo);
}
复制代码
我们知道 ServiceMethod
负责解析方法参数的注解,我们来看看它遇到 @Body
是如何解析的吧:
private ParameterHandler<?> parseParameterAnnotation(
//...
} else if (annotation instanceof Body) {
//...
Converter<?, RequestBody> converter;
try {
converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
} catch (RuntimeException e) {
//...
}
gotBody = true;
return new ParameterHandler.Body<>(converter);
}
//...
}
复制代码
可以看到,在解析参数注解时,遇到注解是 Body
时,会调用 retrofit.requestBodyConverter()
,这个方法和前面寻找转换响应数据的 responseConverter
一样,都是遍历 Retrofit
中的转换器工厂列表。
最常使用的转换器工厂是 GsonConverterFactory
,我们来看看它定义的请求体解析器是什么样的:
//GsonConverterFactory.requestBodyConverter()
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
//GsonRequestBodyConverter.convert()
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
复制代码
可以看到,使用 Gson 实现的请求体转换器比较简单,就是拿到 Type 后创建一个 TypeAdapter
,然后读取数据,将它转成 RequestBody
。
接着看看拿到网络响应响应体 ResponseBody
后,如何转换成用户指定的类型。
在 OkHttpCall
的同步或者异步请求最后,都调用了 parseResponse()
方法,这个方法除了根据响应码做回调,最后还做了转换工作:
//OkHttpCall.parseResponse
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
//...
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
//...
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
//...
throw e;
}
}
复制代码
又见 ServiceMethod
,这哥们从请求开始到请求结束,一直负责重要的功能,大家一定要记住它!!!
ServiceMethod.toResponse()
方法也很简单,就是调用转换器:
//ServiceMethod.toResponse
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
复制代码
还是看看常用的 Gson 响应转换器:
//GsonConverterFactory.responseBodyConverter()
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
//GsonResponseBodyConverter.convert()
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
复制代码
很简单就两步:
根据方法中的返回值数据类型 Type 创建 TypeAdapter
调用 JsonReader 进行读取,将 ResponseBody
转换成指定的类型
具体 Gson 原理这里就暂不赘述了。
OK 小结一下 Retrofit
如何转换请求、响应信息: 两个转换器搞定!
Retrofit 请求实现流程总结
一张图总结 Retrofit
网络请求实现原理:
Retrofit
中最核心的就这几点:
动态代理,代理类做了什么工作要清楚
老熟人 ServiceMethod
都做了什么重要的工作
CallAdapter
负责将方法里的返回值转换成上层的 OkHttpCall
两个 Converter
分别实现自己传的对象到请求体、响应体到自己定义的对象的转换
看着流程图能把这四点说明白,你就掌握了!
评论