retrofit github地址
retrofit官方文档地址
Retrofit是square公司开源的一款类型安全的http请求框架,用于Java和Android程序。Retrofit实际上在Okhttp的基础之上又进行了一次封装,将Okhttp的使用方式转换成了对象的方法调用的形式
我写的关于okHttp文章
下面是Retrofit的简单调用
public interface RetrofitInterface {
@GET
Call getRetrofitGet(Map<String, Object> params);
@POST
Call getRetrofitPost(Map<String, Object> params);
@PUT
Call getRetrofitPut(Map<String, Object> params);
@DELETE
Call getRetrofitDelete(Map<String, Object> params);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.build();
RetrofitInterface retrofitInterface=retrofit.create(RetrofitInterface.class);
Call<String> call = null;
if(requestType==GET_TYPE){
call=retrofitInterface.getRetrofitGet(params);
}else if(requestType==POST_TYPE){
call=retrofitInterface.getRetrofitPost(params);
}else if(requestType== DELETE_TYPE){
call=retrofitInterface.getRetrofitDelete(params);
}else if(requestType==PUT_TYPE){
call=retrofitInterface.getRetrofitPut(params);
}
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
String result=response.body().toString();
callBack.onSuccess(response.code(),result);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
callBack.onError((Exception) t);
}
});
以上就是一个使用Retrofit发起http请求的完整的例子,首先,定义一个服务接口类,声明要发起请求的方法;然后在需要发起网络请求的地方生成一个retrofit实例,利用retrofit.create()生成一个服务接口类的对象,然后调用对象的方法完成请求
使用Retrofit的七步骤
- 添加Retrofit依赖,网络权限
- 定义接收服务器返回数据的Bean
- 创建网络请求的接口,使用注解(动态代理,核心)
- builder模式创建Retrofit实例,converter,calladapter...
- 创建接口实例,调用具体的网络请求
- call同步/异步网络请求
- 处理服务器返回的数据
Retrofit网络通信八步骤
- 创建Retrofit实例
- 定义网络请求接口,并为接口中的方法添加注解
- 通过动态代理生成网络请求对象
- 通过网络请求适配器将网络请求对象进行平台适配
- 通过网络请求执行器,发送网络请求(call)
- 通过数据解析器解析数据
- 通过会掉执行器,切换线程
- 用户在主线程处理返回结果
Retrofit的优点
- 超级解耦 ,接口定义、接口参数、接口回调不在耦合在一起
- 可以配置不同的httpClient来实现网络请求,如okhttp、httpclient
- 支持同步、异步、Rxjava
- 可以配置不同反序列化工具类来解析不同的数据,如json、xml
- 请求速度快,使用方便灵活简洁
Retrofit注解
在上面的例子中,有看到我使用的注释,在Retrofit中有如下注解
注解名 | 说明 |
---|---|
网络请求方法 | |
@GET | get请求 |
@POST | post请求 |
@PUT | put请求 |
@DELETE | delete请求 |
@PATCH | patch请求,该请求是对put请求的补充,用于更新局部资源 |
@HEAD | head请求 |
@OPTIONS | options请求 |
@HTTP | 用于替换以上7个注解的作用及更多拓展功能 |
网络请求参数 | |
@Headers | 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在 |
@Header | 作为方法的参数传入,用于添加不固定的header,它会更新已有请求头 |
@Body | 多用于Post请求发送非表达数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据,添加GsonConverterFactory则是将body转化为json字符串进行传递 |
@Filed | 多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数 |
@FiledMap | 多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用 |
@Part | 用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况 |
@PartMap | 用于表单字段,默认接受类型是Map<String,RequestBody>,可用于实现多文件上传 |
@Path | 用于Url中的占位符 |
@Query | 用于Get请求中的参数 |
@QueryMap | 与Query类似,用于不确定表单参数 |
@Url | 指定请求路径 |
标记 | |
@FromUrlCoded | 表示请求发送编码表单数据,每个键值对需要使用@Filed注解 |
@Multipart | 表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值 |
@Streaming | 表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用 |
Retrofit使用
网络请求方法
1.@GET、@POST、@PUT、@DELETE、@HEAD分别对应 HTTP中的网络请求方式
2.@HTTP替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用 及 更多功能拓展
具体使用:通过属性method、path、hasBody进行设置
//get请求
@GET("url")//@GET为 调用此方法会发起get请求 “user”我get请求的url地址
Call<T> geResponse();//T为请求完成返回的ResponseBody
//拼接完地址为http://192.168.0.1/url
@POST("url/post") //post请求
Call<ResponseBody> getPostResponse();
@HTTP(method = "GET", path = "user/keys", hasBody = false)
Call<ResponseBody> getHttpResponse();
请求标记
1.@FormUrlEncoded
表示发送form-encoded的数据,每个键值对需要用@Filed来注解键名,随后的对象需要提供值。
/**
*表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
* <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
*/
@POST("/form")
@FormUrlEncoded
Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
2.@Multipart
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);
网络请求参数
1.@Header & @Headers
添加请求头 &添加不固定的请求头
区别在于使用场景和使用方式
- 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
- 使用方式:@Header作用于方法的参数;@Headers作用于方法
// @Header
@GET("user")
Call<User> getResponse(@Header("Authorization") String authorization)
// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getResponse()
2.@Body
以 Post方式 传递 自定义数据类型 给服务器,如果提交的是一个Map,那么作用相当于 @Field,不过Map要经过 FormBody.Builder 类处理成为符合 Okhttp 格式的表单。也可以做上传json格式数据,直接传入实体它会自动转为json,这个转化方式可以是GsonConverterFactory定义的,@Body可以传递自定义类型数据给服务器,多用于post请求发送非表单数据,比如用传递Json格式数据,它可以注解很多东西,比如HashMap、实体类等。
@FormUrlEncoded
@POST("url/emails")
Call<ResponseBody> getPsotDataBodyResponse(@Body RequestBody body);
3.@Field & @FieldMap
发送 Post请求 时提交请求的表单字段,与 @FormUrlEncoded 注解配合使用
- @Field 请求参数注解,提交请求的表单字段,必须要添加,而且需要配合@FormUrlEncoded使用,与get的Query一样
- @FieldMap 请求参数注解,与@Field作用一致,用于不确定表单个数是传参数
@FormUrlEncoded//请求格式注解,请求实体是一个From表单,每个键值对需要使用@File注解
@POST("url/post") //post请求
Call<ResponseBody> getPostResponse2(@Field ("id") int id, @Field ("username") String username);
@FormUrlEncoded
@POST("url/post")
Call<ResponseBody> getPostResponse3(@FieldMap Map<String, Object> map);
4.@Part & @PartMap
发送 Post请求 时提交请求的表单字段,与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景,与 @Multipart 注解配合使用
/**
* {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
* 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part}
* 中已经包含了表单字段的信息),
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name
, @Part("age") RequestBody age, @Part MultipartBody.Part file);
/**
* PartMap 注解支持一个Map作为参数,支持 {@link RequestBody } 类型,
* 如果有其它的类型,会被{@link retrofit2.Converter}转换,如后面会介绍的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
* 所以{@link MultipartBody.Part} 就不适用了,所以文件只能用<b> @Part MultipartBody.Part </b>
*/
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);
@POST("/form")
@Multipart
Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
5.@Query和@QueryMap
用于 @GET 方法的查询参数(Query = Url 中 ‘?’ 后面的 key-value)
如:url = http://www.println.net/?cate=android,其中,Query = cate
配置时只需要在接口方法中增加一个参数即可:
用法与Post的@Field & @FieldMap相似
@GET("url")
Call<ResponseBody> geResponse2(@Query("id") int id, @Query("username") String username);
//其实就是(int id,String username)在两个参数的前面加上参数注释@query
//拼接完地址为http://192.168.0.1/url?id=10&username=lucifer
@GET("url")
Call<ResponseBody> geResponse3(@QueryMap Map<String, Object> map);
//与上面一样,只不过传入的id,与username都被放到了Map集合里面
//拼接完地址为http://192.168.0.1/url?id=10&username=lucifer
6.@Path
URL地址的缺省值
@GET("url/{userId}")//@GET为 调用此方法会发起get请求 “user”我get请求的url地址
Call<T> geResponse(@Path("userId") String userId);//T为请求完成返回的ResponseBody
//拼接完地址为http://192.168.0.1/url/{userId} path指url中的可变参数
7.@Url
直接传入一个请求的 URL变量 用于URL设置
@GET
Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
// 当有URL注解时,@GET传入的URL就可以省略
// 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供
Retrofit源码解析
我们先看看创建Retrofit构造方法
public final class Retrofit {
//网络请求缓存,如:请求方法、请求头、请求体,各种适配器等
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
//okhttp工厂,真正发送交易的处理类
final okhttp3.Call.Factory callFactory;
//请求url前半部,基地址
final HttpUrl baseUrl;
//数据转换器工厂集
final List<Converter.Factory> converterFactories;
//网络请求适配器工厂集
final List<CallAdapter.Factory> callAdapterFactories;
//异步请求结果线程切换执行器
final @Nullable Executor callbackExecutor;
//标志位、是否马上解析接口方法
final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
...
public static final class Builder {
//适配平台,通常默认android
private final Platform platform;
//okhttp网络请求工厂,默认okhttp
private @Nullable okhttp3.Call.Factory callFactory;
//请求地址
private @Nullable HttpUrl baseUrl;
//数据转换器集,用于生产数据转换器,默认GsonConverterFactory
private final List<Converter.Factory> converterFactories = new ArrayList<>();
//网络请求适配器,如RxJava2CallAdapterFactory
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
//执行异步回调的线程切换
private @Nullable Executor callbackExecutor;
//是否立即解析接口注解方法
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
// Do not add the default BuiltIntConverters and platform-aware converters added by build().
for (int i = 1,
size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize();
i < size; i++) {
converterFactories.add(retrofit.converterFactories.get(i));
}
// Do not add the default, platform-aware call adapters added by build().
for (int i = 0,
size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize();
i < size; i++) {
callAdapterFactories.add(retrofit.callAdapterFactories.get(i));
}
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
...
public Retrofit build() {
if (baseUrl == null) {//baseurl不能是空
throw new IllegalStateException("Base URL required.");
}
//callFactory是类okhttp3.Call.Factory的对象,如果自己没有设置了OkHttp对象,则会自己创建一个。
okhttp3.Call.Factory callFactory = this.callFactory; //返回Http的call
if (callFactory == null) {//实现请求的工厂类
callFactory = new OkHttpClient();
}
//回调方法执行器
Executor callbackExecutor = this.callbackExecutor;
//没有指定的话,就用构造器中赋值的platform中的,也就是将回调放在主线程
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 将配置的网络适配器进行保护性拷贝
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//添加默认的网络适配器,也就是ExecutorCallAdapterFactory
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 与网络适配器的排序不同,默认的BuiltInConverters放在第一位,后面才是添加的
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 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);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
我们可以看到,Retrofit与OkHttp的源码类似,都是使用了建造者模式
最开始创建Retrofit.Build对象,创建Builder实例时调用的是Builder的无参构造放法,里面调用了Builder(Platform)这个构造方法,传入的是Platform.get()返回数据,这个方法是获取适配平台,默认是Android
class Platform {
private static final Platform PLATFORM = findPlatform();//PLATFORM 默认的方法
static Platform get() {//Build中调用此方法
return PLATFORM;
}
}
private static Platform findPlatform() {
try {
//如果是安卓系统,就返回Android()
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android(); //返回android
}
} catch (ClassNotFoundException ignored) {
}
try {
// Java8()
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
static class Android extends Platform { //创建android 的平台
//请求结果毁掉是用的Executor,如果Builder没有赋值给callbackExecutor,就会调用这个方法赋值
@IgnoreJRERequirement // Guarded by API check.
@Override boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//Builder里的callAdapter.Factory,最后会在build里赋值给adapterFactories,作为默认的网络请求适配器
@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
@Override int defaultCallAdapterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
}
@Override List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
@Override int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}
static class MainThreadExecutor implements Executor {
//默认线程切换是切换到主线程
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
baseUrl
就是将String类型的url,经过合格性检测,拆分存储,再转换成HttpUrl赋值给baseUrl。
/**
* Set the API base URL.
*
* @see #baseUrl(HttpUrl)
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
在这里可以看到,baseUrl路径必须以"/"结尾
addConverterFactory
//将转换工厂保存到converterFactories中,在构造器中,已经add了一个BuiltInConverters
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
我们可以在这里添加一个GsonConverterFactory,下面来看看它是如何转换的。
public final class GsonConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
//返回对应的Converter对象
return new GsonResponseBodyConverter<>(gson, adapter);
}
}
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
//将ResponseBody转为泛型对象
return adapter.read(jsonReader);
} finally {
value.close();
}
}
通过convert转换的类型,是在调用responseBodyConverter创建对象时传入的请求接口的返回类的泛型。也就是例子中的HttpResult。
如果要自定义Converter来实现请求结果转化,按上面那样就可以了,使用工厂方法模式。
- 继承Converter,在convert方法中返回转换后的结果,比如GsonRequestBodyConverter中是把ResponseBody转成自己需要转的类型。
- 继承Converter.Factory,在responseBodyConverter中将相应的Converter对象返回。
- 在Retrofit的创造器中调用addConverterFactory添加相应的Converter.Factory。
总结
可以看到在创建Builder实例的设配平台时,将工作线程切换到了主线程,这也是后面可以通过主线程回调返回请求数据的原因。
retrofit与OkHttp一样最后会执行build()方法。在build方法中baseUrl不能等于null,如果是null就会抛出IllegalStateException异常,然后会在build方法中创建okhttp3.Call.Factory callFactory对象,在文章开始开始的时候说过,retrofit是基于okHttp的请求的,也就是在这个方法中创建了OkHttp3的对象。然后又创建了一个回调函数Executor callbackExecutor, 他是在Platform中Android的MainThreadExecutor();他是一个Handle,默认的主线程回调执行器。然后通过一系列操作,最后创建Retrofit对象。
defaultCallbackExecutor是返回回调执行的Executor,返回的MainThreadExecutor是使用handler让回调操作在主线程执行。如果在Builder中没有指定回调的Executor,会调用defaultCallbackExecutor指定异步网络请求的回调在主线程执行。
defaultCallAdapterFactory则是指定默认网络适配器工厂为ExecutorCallAdapterFactory,调用接口方法返回的Call,就是这个类创建的。具体等后面使用其功能再介绍。
retrofit.create
我们通过Retrofit的create方法来创建实例,这个方法是Retrofit的核心,内部采用动态代理,将咱们自定义的网络请求接口转换成一个RetrofitInterface 对象,RetrofitInterface 就是咱们Retrofit中的具体请求对象,里面封装了网络请求所必须的全部信息,包括请求方法、url、请求头、请求体等网络配置参数!
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
//是否提前通过注解加验证加载请求接口,会将接口中的方法都解析成ServiceMethod,并加入serviceMethodCache缓存中
if (validateEagerly) {
//注释一
eagerlyValidateMethods(service);
}
//返回了动态代理对象用来实现代理接口
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {//将代理类的实现交给 InvocationHandler类作为具体的实现
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
//被代理执行的方法,是通过在InvocationHandler中的invoke方法调用的
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// Object的方法直接调用原方法
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//android默认为false,不走
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
我们先看注释一处的代码
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
我们可以看到在可以看到在eagerlyValidateMethods这个方法中,遍历获取咱们自定义类的全部方法,。isDefaultMethod默认为false可以忽略并且方法不是静态的,就一定会走到loadServiceMethod(method)方法
ServiceMethod<?> loadServiceMethod(Method method) {
//从缓存中获取,如果先前创建过久直接用
//create中的eagerlyValidateMethods方法会提前创建对象并缓存
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;
}
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> 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);
}
abstract @Nullable T invoke(Object[] args);
}
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method;
private final HttpUrl baseUrl;
final String httpMethod;
private final @Nullable String relativeUrl;
private final @Nullable Headers headers;
private final @Nullable MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
final boolean isKotlinSuspendFunction;
RequestFactory(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
}
static final class Builder {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final Retrofit retrofit;
final Method method;
final Annotation[] methodAnnotations;
final Annotation[][] parameterAnnotationsArray;
final Type[] parameterTypes;
boolean gotField;
boolean gotPart;
boolean gotBody;
boolean gotPath;
boolean gotQuery;
boolean gotQueryName;
boolean gotQueryMap;
boolean gotUrl;
@Nullable String httpMethod;
boolean hasBody;
boolean isFormEncoded;
boolean isMultipart;
@Nullable String relativeUrl;
@Nullable Headers headers;
@Nullable MediaType contentType;
@Nullable Set<String> relativeUrlParamNames;
@Nullable ParameterHandler<?>[] parameterHandlers;
boolean isKotlinSuspendFunction;
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取方法里的注解
this.methodAnnotations = method.getAnnotations();
//获取方法的参数类型
this.parameterTypes = method.getGenericParameterTypes();
//获取方法参数里的注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory build() {
//解析带注释的方法
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "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, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
return new RequestFactory(this);
}
RequestFactory build() { //解析带注释的方法
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "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, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
return new RequestFactory(this);
}
//解析带注释的具体方法
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
从上面的代码中,loadServiceMethod方法,中调用了ServiceMethod.parseAnnotations方法,在这个方法中通过RequestFactory类解析了所有的自定义类中的带注释的方法,且遍历该方法的中的所有注释进行解析,解析完完成后,嗲用RequestFactory的build方法,创建RequestFactory,
接下来我们来看ServiceMethod.parseAnnotations的return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)方法。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> 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) {//判断是不是kotlin的方法,如果是对方法进行处理
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<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();//获取java方法的返回类型
}
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
//异常判断
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;//创建一个OkHttp对象
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
HttpServiceMethod ->CallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
//通过retrofit的callAdapter方法返回的
return (CallAdapter<ResponseT, ReturnT>) 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);
}
}
Retrofit-> callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
Retrofit->nextCallAdapter
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());
}
HttpServiceMethod->Converter
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
Retrofit->responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
Retrofit->nextResponseBodyConverter
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
//默认的数据转换器BuiltInConverters,如果接口方法返回值类型不是ResponseBody和Void的话,返回null
//分析的这个例子中,接口方法返回值的泛型是HttpResult,所以会循环到下个GsonConverterFactor对象
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = converterFactories.size(); i < count; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
从上面的代码中看到最后在Retrofit->nextCallAdapter,获取在Retrofit进行build时,创建的CallAdaptaer对象,然后在获取converterFactories的转换器集合对象,在最后在创建HttpServiceMethod对象
然后我们回到create方法中,返回了一个动态代理的对象,真正处理代码的是在动态代理的invoke方法。接着我们来查看invoke方法
HttpServiceMethod->invoke
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}
我们看到在invoke方法中,用调用了callAdapter.adapt(方法)
这个CallAdapter实际上是从DefaultCallAdapterFactory中的get方法中获取详见 HttpServiceMethod方法的CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);代码
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> 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<T> 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<T> 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<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
}
上面的源代码有三点需要注意
1:看那个get(),就是这里返回了我起调函数的那个callAdapter,所以adapt(),执行的就是
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
2这里面还有一个CallbackExecutor,这个是在retrofit构建时候传入的,Android平台默认为MainThreadExecutor
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
这里使用了典型的代理模式,不过这次是静态代理。ExecutorCallbackCall 代理了OkHttpCall,他们都实现了接口Call。
至此create方法算是看完了
发起请求enqueue
接下来我们看retrofit2的OkHttpCall中的enqueue方法
@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是okhttp的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) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@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(); // TODO this is not great
}
}
});
}
代码比较简单,我么我一看到代码中,先通过createRawCall方法创建Call对象,然后调用call.enqueue发起真正的请求,最后在通过parseResponse(rawResponse)解析返回的response方法
我们先来看createRawCall方法
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
RequestFactory->create
okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
headers, contentType, hasBody, isFormEncoded, isMultipart);
if (isKotlinSuspendFunction) {
// The Continuation is the last parameter and the handlers array contains null at that index.
argumentCount--;
}
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.get()
.tag(Invocation.class, new Invocation(method, argumentList))
.build();
}
我们知道要创建一个okhtt3.call,需要使用okhttp的Call.Factory.newCall(Request r)的方法,那个callFactory就是我们的工厂,而Request是由RequestFactory.create()的方法创建的,create方法可以说是至关重要,我们前面搞来搞去就是为了能生成一个okhttp3的一个Request。
然后我们接着看parseResponse(rawResponse)方法
Response<T> 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();//这里与okhttp3一样,将返回值封装成一个Response对象
int code = rawResponse.code();
if (code < 200 || code >= 300) { //如果请求服务器返回值出错
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {//返回204 205
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);//关键代码
try {
T body = responseConverter.convert(catchingBody);//关键代码
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
OkHttpCall->ExceptionCatchingResponseBody
static final class ExceptionCatchingResponseBody extends ResponseBody {
private final ResponseBody delegate;
private final BufferedSource delegateSource;
@Nullable IOException thrownException;
ExceptionCatchingResponseBody(ResponseBody delegate) {
this.delegate = delegate;
this.delegateSource = Okio.buffer(new ForwardingSource(delegate.source()) {
@Override public long read(Buffer sink, long byteCount) throws IOException {
try {
return super.read(sink, byteCount);
} catch (IOException e) {
thrownException = e;
throw e;
}
}
});
}
@Override public MediaType contentType() {
return delegate.contentType();
}
@Override public long contentLength() {
return delegate.contentLength();
}
@Override public BufferedSource source() {
return delegateSource;
}
@Override public void close() {
delegate.close();
}
void throwIfCaught() throws IOException {
if (thrownException != null) {
throw thrownException;
}
}
}
将返回的okhttp3的response解析为retrofit的response。关键是是通过responseConverter将返回数据解析成我们在接口声明文件中提供的数据类型,就是那个callAdapter里面的responseType(),其是由returnType得到的,而 returnType = method.getGenericReturnType();,就是我们声明时候的泛型类型。
总结:
Retrofit的代码请求部分都是基于OkHttp代码进行
先是创建了Retrofit的实例,与OkHttp一样,都是使用了建造者模式创建的,中间调用了网络请求工厂(okhttp3.Call.Factory),网络请求地址(HttpUrl),数据转换器(List<Converter.Factory>),网络适配器(List<CallAdapter.Factory>),回调执行方法(Executor)
在create方法中接口方法的返回值是网络适配器返回对象,类型要和接口方法的返回值一致。动态代理的invoke方法里,通过Retrofit的配置和接口方法的注解配置生成ServiceMethod对象,这个对象保存了网络请求的所有配置。大部分方法和解析注解生成配置有关,主要关注两个方法:一个toRequest通过RequestBuilder生成OKhttp的Request,toResponse可以利用数据转换器将ResponseBody转为请求接口方法返回值泛型。这两个方法都是给OkHttpCall使用。再通过ServiceMethod创建了OkHttpCall,里面有请求网络的方法,实际上是根据ServiceMethod的配置网络信息生成的Request再生成okhttp3.Call,将请求结果通过ServiceMethod的配置转换器进行数据转换,最终回调给调用它的类(默认ExecutorCallbackCall),在动态代理的invoke方法里,创建ServiceMethod时用get方法生成适配器后,再通过适配器的adapt生成ExecutorCallbackCall返回值,ExecutorCallbackCall中用静态代理模式实现,被代理对象是OkHttpCall。最后在对返回的对象进行解析,可以通过使用GsonConverterFactory的具体转换结果类型,是在创建ServiceMethod时,这个是用解析的接口方法中的返回值泛型确定的。
网友评论