在Retrofit2使用这篇文章中介绍过retrofit的使用,那现在我们通过源码来分析其原理。源码版本Retrofit:2.0.2
compile 'com.squareup.retrofit2:retrofit:2.0.2'
创建Retrofit对象
首先使用了Builder模式创建出Retrofit对象:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //请求地址的域名
.addConverterFactory(GsonConverterFactory.create())//把请求返回的数据解析我们关心的格式,这里我们通过Gson来解析返回的数据
.client(new OkHttpClient())
.build();
创建retrofit对象时需要我们设置几个重要的数据,通过addxxx()方法来设置,域名,数据转换器。client方法可以不用设置,因为retrofit请求的任务默认交给OkHttp处理。
Retrofit框架支持了IOS,Android,Java8平台。默认的平台的Android,需要设置其他平台通过构造函数注入,Builder类中有个带参数的构造函数,如下:
Builder(Platform platform) {
this.platform = platform;
converterFactories.add(new BuiltInConverters());
}
创建接口服务代理
然后调用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, 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);
}
});
}
我们都知道动态代理的一大特点就是,可以在调用目的对象之前和之后可以做一些其它的相关操作。
首先判断,该方法是否属于Object类?直接invoke解析那个方法
: 判断是否是默认的方法?调用platform.invokeDefaultMethod方法来解析那个方法:通过ServiceMethod来解析那个方法。
创建ServiceMethod
我们去分析ServiceMethod是怎么解析那个方法的。
调用loadServiceMethod方法创建ServiceMethod对象,我们去看看:
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
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;
}
首先判断serviceMethodCache缓存是否存在该对象。如果没有通过Builder模式创建ServiceMethod对象,该对象创建出来后会缓存在serviceMethodCache对象中。
我们去看看是怎么build出来的:
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
.......
return new ServiceMethod<>(this);
}
在上述代码做了三个重要的操作:
- 创建CallAdapter,该对象用来管理线程,在Platform类中的defaultCallAdapterFactory方法可以看出:
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
2.创建Converter,用来把返回的数据解析成我们想要的格式。Retrofix提供很多Converter工厂,Gson,xml等
3.解析服务接口的注解。通过解析注解,封装成request对象发送请求。
创建OkHttpCall
直接new出来一个OkHttpCall对象,该对象是OkHttp的封装类,通过该类 ,把请求的任务交给OkHttp处理。
返回代理服务接口对象
生成接口服务代理对象,并返回:
return serviceMethod.callAdapter.adapt(okHttpCall);
最后我们就可以发送请求,等待数据返回:
Call<NewsInfo> newsInfoCall = newsServive.newsListByGetMethod(paramsMap);
//发送异步的请求
newsInfoCall.enqueue(new Callback<NewsInfo>() {
@Override
public void onResponse(Call<NewsInfo> call, Response<NewsInfo> response) {
NewsInfo newsInfo = response.body();
if(newsInfo.getError_code() == REQ_OK){
for (NewsInfo.ResultBean info : newsInfo.getResult()){
Log.d("tag","-----> info = " + info.toString());
}
}else{
Log.e("tag","----> reason = " + newsInfo.getReason());
}
}
@Override
public void onFailure(Call<NewsInfo> call, Throwable t) {
Log.e("tag","-----> error = " + t.getMessage());
}
});
总结整个流程:
END。