Retrofit这个开源库出来也有一定年头了,记得之前还是在V1.0的版本的时候,之前在三月份也写过一个Retrofit的使用简析,那会儿正是1.0向2.0过渡的时候,所以新版本老版本对比了一下!时至今日,相关文章已经层出不穷了,今天主要是打开它的源码,了解一些细节的问题!
准备工作
基于版本:
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'
相关问题:
1、Retrofit是使用注解确定对应的请求方式和参数的,那么具体的url是怎么产生出来的的呢?
2、我们定义的是一个接口,那么Retrofit又是怎么生成对应的实现类的呢?
3、网络请求V2.0开始统一使用OkHttp了,那么异步回调到主线程是如何实现的?
4、同一个方法,支持Call<T>
的返回类型,又可以支持Observable<T>
的返回类型,这个又是如何实现的?
5、同一个方法,支持不同的转换(Gson
、Jackson
、Moshi
、FastJson
等等),这个又是如何实现的呢?
带着这些问题,我们可以更好的进行相关的源码分析
第一部分 Retrofit && ServiceMethod的创建
从Retrofit的构建方法开始说起
new Retrofit.Builder()
.baseUrl("http://10.0.60.115:60321/1.0/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(RequestUtils.createLoginJsonRequest(chain.request()));
}
})
.addNetworkInterceptor(
new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
.build())
.build()
.create(LoginApi.class);
这里就是显而易见的builder模,通过Builder去构建我们需要的一些必要数据(比如说baseUrl,callAdapter,Conver等等),接下来看看Builder里面具体做了些什么!!
调用Retrofit内部的Builder的空参数构造方法!:
public Builder() {
this(Platform.get());
}
Builder(Platform platform) {
this.platform = platform;
// 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());
}
在这里,又去调用了Platform.get()
初始化了一个Platform
,并把默认的转换器BuiltInConverters
初始化并加入了集合中!!
那么问题来了,这个Platform
是何方神圣,具体有撒作用??顺藤摸瓜,这里开始介绍内部的第一个神秘嘉宾!!
Platform 初始化
private static final Platform PLATFORM = findPlatform();//初始化`Platform`的静态方法
Platform
字面意思就是平台啦,所以Platform
相当于一个抽象类,这个类里面有对应的实现类:Android iOS Java 8对应的是各种具体平台。
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
可以看到,在调用findPlatform()
方法之后就回去判断初始化对应的具体平台,具体的实现类就是上面说到的三个,Android Java iOS,你没有看错,还有iOS的(这里是用的Swift
),啧啧。。
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
各个不同的平台其实就是根据不同的环境初始化不同的MainThreadExecutor
,像上面的Android平台当然就是获取主线程的Handler
!!这里可以看到,在初始化Platform
之后,通过Platform
得到的ExecutorCallAdapterFactory
的工厂的Executor
其实就是运行在主线程的Executor
!
Builder
的默认构造函数基本上讲完了!其实就是通过对应的平台构建了一个具体的Platform
,通过这个Platform
构建出了对应平台的主线程队列的线程池,方便后面的方法回调到主线程中!这里基本上也可以回答第三个问题了,异步怎么回调到主线程的!
添加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;
}
这里没撒说的,就是检测一下url的格式,然后完成赋值!
addConverterFactory && addCallAdapterFactory
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
这里忍不住必须说两句了,这两个方法套路是完全一样——适配器模式,CallAdapter
是请求Call
对应的适配器,CallAdapter.Factory
是创建对应CallAdapter
的抽象工厂!! Converter
是解析的转换器,这里提供了三种转换场景,responseBodyConverter
、requestBodyConverter
、stringConverter
。Converter.Factory
则是Convert
的抽象工厂,这样利于我们的后期扩展,比如说外国人肯定没有写对应FastJson
的Covert
,但是它提供了工厂的嘛,我们继承这个抽象工厂,实现出来就好了!!
RxJavaCallAdapterFactory
在RxJavaCallAdapterFactory这个工厂中,又定义了两种 ,一种是SimpleCallAdapter
另外一种是ResultCallAdapter
,
//SimpleCallAdapter
@Override public <R> Observable<R> adapt(Call<R> call) {
Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
.flatMap(new Func1<Response<R>, Observable<R>>() {
@Override public Observable<R> call(Response<R> response) {
if (response.isSuccessful()) {
return Observable.just(response.body());
}
return Observable.error(new HttpException(response));
}
});
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
//ResultCallAdapter
@Override public <R> Observable<Result<R>> adapt(Call<R> call) {
Observable<Result<R>> observable = Observable.create(new CallOnSubscribe<>(call)) //
.map(new Func1<Response<R>, Result<R>>() {
@Override public Result<R> call(Response<R> response) {
return Result.response(response);
}
}).onErrorReturn(new Func1<Throwable, Result<R>>() {
@Override public Result<R> call(Throwable throwable) {
return Result.error(throwable);
}
});
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
通俗的说其实就是根据返回值类型判断返回的Observable
是否需要处理一下对应的Response
!!使用flatMap()
将其包装为一个新的Observable
返回!!
Retrofit在创建的build()
方法:
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//添加完之后再添加一个defaultCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
//这个方法是上面提到的platform里面的方法,通过这个方法,将主线程的线程池和ExecutorCallAdapterFactory关联起来了!!
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
到这里,Builder的创建过程分析完毕,总结起来就是创建出具体的Platform
,通过具体的Platform
创建出主线程的线程池,然后构建出默认的ExecutorCallAdapterFactory
,另外就是添加对应的CallAdapter.Factory
(比如说RxJavaCallAdapterFactory 等)和Converter.Factory
!
生成接口的代理对象
build()
方法创建对应的Retrofit
之后就是create(Class<T> service)
的方法,这里就是生成对应的接口的代理类的方法!!
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
可以看到,在调用create()
方法之后,是通过Proxy
生成对应的动态代理!这里就很好说咯,在对应的invoke()
的方法中完成具体的请求!
如果Java
的动态代理不清楚或者已经忘记了的亲们,这里先简单脑补一下,代理的对应方法最后都会交给InvocationHandler
这个类,并通过invoke(Object proxy, Method method, Object... args)
的方法去执行相关的逻辑,这里的Method是对应具体方法的信息摘要,反射对象,里面包含了method的名称,参数类型,包括注解那些反正是应有尽有啦!这个args就是具体的方法参数了!
接下来就要注意啦,在创建好了Retrofit之后,在生成动态代理之后,咱们的请求方法还没有构建出来呢!所以呢,接下来肯定就是构建相关的请求方法咯!!
但是明确看到,在返回动态代理之前我们看到这里有一个判断validateEagerly
,而且对应的Builder 对外提供了一个设置的方法!
/**
* When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
* the configuration of all methods in the supplied interface.
*/
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
这个方法到底是来做撒的呢?英语好的应该都看明白了!我先绕个关子不讲了!!
直接到代理的invoke()
方法中,这里有两个条件判断,第一个是判断返回的类型如果就是Object,那就撒都不搞了,直接执行!
第二个判断如果这个方法是Default的,这个主要是针对java8来说得呢!所以重点还是要跳过到最下面!
ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod的创建
继上面说过的Platform
之后,ServiceMethod
是我们开始讲解的第二个类了!这里开始创建出对应的ServiceMethod
对象,到这个方法里面具体看看!
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
举个例子,比如说我们在LoginApi这个接口里面定义了两个方法:
@POST("users")//https://api.bmob.cn/1/ 注册用户
Call<UserBean> registerUser( @Body UserBean bean);
@GET("getUserInfo")//https://api.bmob.cn/1/用户登陆
Observable<Result<UserBean>> login(@QueryMap Map<String,String> map);
那么当我们执行login()
方法的时候,就会创建Retrofit
,并且创建这个LoginApi
的动态代理,然后调用login()
方法,那么这里loadServiceMethod(Method method)
中的method方法就是login()
这个方法的对象。然后通过ServiceMethod.Builder
去构建这个具体的ServiceMethod
。
//ServiceMethod.Builder的构造方法
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//获取方法的对应注解@retrofit2.http.POST(value=files/{fileName})
this.parameterTypes = method.getGenericParameterTypes();//获取方法参数的类型
this.parameterAnnotationsArray = method.getParameterAnnotations();//获取方法参数的注解
}
接下来重点看看ServiceMethod.Builder.builder()
的构建过程!这里算是Retrofit
里面比较重要的一块了吧,因为它要开始拼接url、确定返回类型、明确CallAdapter
和responseConverte
!
public ServiceMethod build() {
//1、获取对应的callAdapter
callAdapter = createCallAdapter();
//2、获取对应的response的类型
responseType = callAdapter.responseType();
//3、创建response的转换器
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
//4、根据方法的注解(GET POST)开始具体的解析
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];
........
//5、解析对应的方法参数注解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
-
1、获取对应的callAdapter
private CallAdapter<?> createCallAdapter() { //获取返回值的Type,后面会用到 Type returnType = method.getGenericReturnType(); ...... Annotation[] annotations = method.getAnnotations(); try { //调用retrofit的方法 return retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } } //callAdapter()方法最终调用nextCallAdapter()来确定具体的callAdapter public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { .... int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { //get是抽象方法,由具体的factory去实现 CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } ..... }
前面在说Retrofit的初始化的时候,就说了默认会添加ExecutorCallAdapterFactory
,如果我们添加了RxJava支持了添加一个RxJavaCallAdapterFactory
的话,那我们这里就有两个CallAdapter
了,那么Retrofit是如何明确到底应该使用哪个Adapter的呢?(问题四)相关的答案都在get()
的方法中!我们可以看看这两个Factory里面具体的get方法是怎么处理的!
//ExecutorCallAdapterFactory中
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//可以处理Call的返回类型
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
//RxJavaCallAdapterFactory中
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
String canonicalName = rawType.getCanonicalName();
boolean isSingle = "rx.Single".equals(canonicalName);
boolean isCompletable = "rx.Completable".equals(canonicalName);
//可以处理 Observable rx.Single rx.Completable的类型
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
....
}
答案很是清晰明了啊,不同的adapter
在get()中处理不同的逻辑!
- 2、获取对应的response的类型
这里的response其实就是之前的获取到的returnType在获取到的里面的具体类型,比如说returnType是Call<UserInfo>,那么这里就获取到对应的UserInfo,相关方法封装放在Utils这个工具类中滴!!
-
3、创建response的转换器
private Converter<ResponseBody, T> createResponseConverter() { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create converter for %s", responseType); } } public <T> Converter<ResponseBody, T> nextResponseBodyConverter(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++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { //noinspection unchecked return (Converter<ResponseBody, T>) converter; } } .... }
这里其实和前面的创建CallAdapter
的原理是一致的!最后调用Retrofit
的responseBodyConverter()
方法,最后调用nextResponseBodyConverter()
的方法,这里这个行为模式就是传说中的责任链模式吧!如果添加了多个,json解析的是要放最后面的,因为它是来者不拒的了!!
- 4、根据方法的注解(GET POST)开始具体的解析
到这里就要开始解析方法上的对应注解了!
比如说下面这个Get请求:
@GET("news/before/{date}")
Observable<DailyStories> getBeforeDailyStories(@Path("date") String date);
在通过parseMethodAnnotation()
方法之后,会继续执行parseHttpMethodAndPath("GET", ((GET) annotation).value(), false)
的方法!
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);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} 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("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
在parseHttpMethodAndPath()
中进行httpMethod、hasBody、relativeUrl、relativeUrlParamNames的赋值!
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
...
this.httpMethod = httpMethod;//GET
this.hasBody = hasBody;//false
...
this.relativeUrl = value;//news/before/{date}
this.relativeUrlParamNames = parsePathParameters(value);
}
最后一个parsePathParameters()
需要我们着重看一下,到这就要进行相关{date}的替换了!
static Set<String> parsePathParameters(String path) {
//static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
Matcher m = PARAM_URL_REGEX.matcher(path);
Set<String> patterns = new LinkedHashSet<>();
while (m.find()) {
patterns.add(m.group(1));
}
return patterns;
}
因为{date}
这一块是需要替换成方法参数里面对应的那个具体值的,这里通过relativeUrlParamNames()
的方法,先将{date}取出存入了set集合中!!方便后面根据方法上对应的参数进行替换!!
解析对应的方法参数
接下来就是解析方法对应的参数的注解了:
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
这里出现了一个新的类ParameterHandler,这也是第三个需要介绍的类了!
ParameterHandler
如图所示,ParameterHandler
它是一个抽象类,有这么多具体的实现小弟来管理某个具体参数!里面还有一个抽象方法apply()
需要每个子类去实现的。这个方法将在后面将具体参数封装到RequestBuilder
里面。在上面举例的方法:
//parameterCount=1,parameterTypes[0]=String.class
getBeforeDailyStories(@Path("date") String date)
所以最后就是执行parseParameter(0,String,Path)
,并且返回的就是ParameterHandler
的对象!接下来具体看内部是怎么操作的。
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
这里接着去调用parseParameterAnnotation()
的方法,这也是ParameterHandler
具体创建的方法!
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
...
} else if (annotation instanceof Path) {
...
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
//创建出对应的PathParameterHandler!!
return new ParameterHandler.Path<>(name, converter, path.encoded());
} .......
return null; // Not a Retrofit annotation.
}
这里会根据不同的类型创建不同的Convert
,比如说解析Path就是使用StringConver,并且会先调用validatePathName()
的方法去判断之前的Set集合里面是否有这个值,如果有,那么就创建出一个ParameterHandler.Path
的对象!
同理解析Body
的时候就会去调用nextRequestBodyConverter()
的方法最终确认对应的Convert
,就这样,最后创建出了ParameterHandler.Body
这个具体的ParameterHandler
对象!并且相关方法的参数的注解也解析出来并封装到了parameterHandlers
数组中!
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
到了这里,ServiceMethod
的初始化完成,那么每次都去辛辛苦苦的构建这些注解和参数是不是太累了?!所以必须把它缓存起来咯!这里也是上面提出的那个validateEagerly
和eagerlyValidateMethods()
问题的答案:如果我们需要尽快构建出每个方法的ServiceMethod,那么就将validateEagerly
设置为true就好了!
第二部分 HTTP请求 响应 转换
经过上面一系列的准备工作,接下来就是开始相关的网络请求了!回到Retrofit
的代理方法中:
//上面已经创建好对应的ServiceMethod了!
ServiceMethod serviceMethod = loadServiceMethod(method);
//初始化OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//执行具体的call
return serviceMethod.callAdapter.adapt(okHttpCall);
OkHttpCall
没有记错的话,OkHttpCall
是我们要介绍的第四个对象了!也是比较重要的一个对象了,OkHttpCall
实现了 Call
接口,内部持有okhttp3.Call
的引用,所以可以理解为它是OkHttp
的Call
的代理对象!
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
这里构建出一个具体的OkHttpCall
的对象!然后调用了serviceMethod.callAdapter.adapt(okHttpCall)
这个方法,接下来着重分析这个方法做了些什么操作!
adapt()
是CallAdapter
里面的抽象方法,由具体的子类实现!如果我们返回的是Call
类型的,那么由上面第一部分分析,ServiceMethod
这里就是是用的ExecutorCallAdapterFactory
!那么到ExecutorCallAdapterFactory
中看看具体的实现逻辑!!
@Override
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
这里又返回了一个ExecutorCallbackCall
的对象!这里的callbackExecutor
就是在讲初始化Platform
创建的!
当我们调用具体的方法时:
login.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
}
});
其实就是调用ExecutorCallbackCall
里面的对应方法咯!
@Override
public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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);
}
});
}
});
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
通过上面的方法就可以完全明白为什么enqueue
的方法都是在主线程上的了!!
这里的delegate
就是之前传入的OkHttpCall
对象,所以这里又会去执行OkHttpCall
里面的enqueue()
方法,绕了半天,终于又回到了OkHttpCall
里面了!
@Override
public void enqueue(final Callback<T> callback) {
....
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//如果call没有创建那么就去创建!
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
....
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
这个方法有点儿长,主要是判断有木有创建okhttp3.Call
,没有就去创建,创建了就调用call的call.enqueue()
方法,最后再将结果通过传入的Callback
回调出去!
RequestBuilder
先说okhttp3.Call
的创建:
call = rawCall = createRawCall();
这里调用了OkHttpCall
里面的createRawCall()
方法:
private okhttp3.Call createRawCall() throws IOException {
//首先创建出okhttp3.Request
Request request = serviceMethod.toRequest(args);
//通过request构建 okhttp3.Call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
那么从这里开始,这些任务又回到了ServiceMethod
这个类中了!所以说ServiceMethod
完全服务于Http请求响应的相关过程!
/** Builds an HTTP request from method arguments. */
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
它构建出一个RequestBuilder
的类,这也是第五个需要讲解的类了!看名字都知道它就是用来构建Request
的Builder
啦!,构建出Builder之后,注意这次是带上具体的参数过来的,所以它会进行参数的封装,构建出最终要去请求的url!!之前有说过对应的每个参数注解已经封装到ParameterHandler
这个类中了,这里就需要遍历parameterHandlers
这个数组,完成对每一个参数的具体赋值,赋值其实也很简单,就是依次调用各个ParameterHandler
的apply(requestBuilder, arg)
方法,apply()
方法其实就是调用之前构建好的Convert
将对应的参数(arg)解析成Request里面具体需要的对象!里面StringConvert
居多!比如之前说到的@Body
的情况(第一部分的结尾)!,因为Body
你也可以传入一个Bean
对象,所以不一定使用的是StringConvert
,这里它会通过nextRequestBodyConverter()
遍历寻找合适Convert。
比如说调用了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());
}
接着就是调用requestBuilder.build()
的方法了!
Request build() {
//1.构建HttpUrl
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
// No query parameters triggered builder creation, just combine the relative URL and base URL.
url = baseUrl.resolve(relativeUrl);
if (url == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
}
2.构建RequestBody
RequestBody body = this.body;
if (body == null) {
// Try to pull from one of the builders.
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
// Body is absent, make an empty body.
body = RequestBody.create(null, new byte[0]);
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
requestBuilder.addHeader("Content-Type", contentType.toString());
}
}
return requestBuilder
.url(url)
.method(method, body)
.build();
}
到这里Request终于是构建好了!接下来是真正的去创建okhttp3.Call
了!
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
这里其实最终使用的是Retrofit
里面构建的okhttp3.Call.Factory
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Response
最后终于到结果的位置了,这个Response也是我们要介绍的第六个对象了!它算是okhttp.Response
的一个装饰类吧!也是最后返回给调用者使用的类!
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();
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) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(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;
}
}
无论是同步或者异步的方法,最后总会通过parseResponse()
的方法将okhttp3.Response
包装为Response
对象返回!!而具体的解析又会交给ServiceMethod
里面的的toResponse()
去处理!!
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
其实就是调用之前确认好的responseConverter
去解析对应的Body
!
到这里,http请求完成,结果也被封装为指定的对象返回了!
总结
1、Call
(接口):向服务器发送请求并返回响应的调用;
2、CallAdapter
(接口):Call
的适配器,将Call适配为不同的类型返回(Call、Observable);
3、CallBack
(接口):顾名思义Call的回调,Call
执行时的回调;
4、Converter
(接口):数据转换器,将一个对象转化另外一个对象;
5、CallAdapter.Factory
(接口):CallAdapter
的工厂,通过get()
方法获取CallAdapter,使用adapt()
执行对应的Call
请求;
6、Converter.Factory
(抽象类) : 数据转换器Converter
的工厂;
-
responseBodyConverter
:将ResponseBody转换为具体的对象。 -
requestBodyConverter
: 将对应的Body
,Part
和PartMap
注解转换为RequestBody(OkHttp3)
,以便http请求的时候使用。 -
StringConverter
:将Field
,FieldMap
值,Header
,Path
,Query
,和QueryMap
值转化为String
,以便http请求的时候使用。
7、ParameterHandler
: 方法参数的处理类;
8、ServiceMethod
:请求方法的生成处理类,用于确定CallAdapter
、ResponseConverter
,生成具体的请求Request
,解析对应的Response
数据,算是一个灰常重要的类了;
9、Platform
:确认不同运行环境的类;
10、OkHttpCall
:实现Call
接口,是okhttp3.Call
的代理类,获取传入的Call,通过Retrofit.callFactory
执行Call
请求,获取数据并使用ResponseConverter
进行解析;
再回到之前说的那些问题上:
1、Retrofit是使用注解确定对应的请求方式和参数的,那么具体的url是怎么产生出来的的呢?
(ServiceMethod里面的相关处理)
2、我们定义的是一个接口,那么Retrofit又是怎么生成对应的实现类的呢?
(动态代理)
3、网络请求V2.0开始统一使用OkHttp了,那么异步回调到主线程是如何实现的?
(MainThreadExecutor)
4、同一个方法,支持Call<T>的返回类型,又可以支持Observable<T>
的返回类型,这个又是如何实现的?
(确定对应CallAdapter
!)
5、同一个方法,支持不同的转换(Gson、Jackson、Moshi、FastJson等等),这个又是如何实现的呢?
(确定对应的Convert!)
搞了这么久,学习到什么呢?从一开始的一脸懵逼到最后的暗自窃喜,这也算是一种进步吧!其中不得不提的是各种设计模式的使用,模块间解耦和扩展的思想!创建型的抽象工厂模式、Builder模式;结构性的代理模式、adapter模式、装饰者模式;行为性的责任链模式等等。。
---- Edit By Joe ----