Retrofit2源码解析(一)

开车:

用了这么久的Retrofit2,是时候了解一波源码,做为一名新司机是时候开始飙一波车,系好安全带,车飘弯大,你还不了改一下

 

正文:

基于以下Retrofit2配置,解析源码

  //Retrofit2
    compile'com.squareup.retrofit2:retrofit:2.3.0'
    compile'com.squareup.retrofit2:converter-gson:2.3.0'
    compile'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

一.

Retrofit retrofit= Retrofit.Bulider();

说明Retrofit是通过建造者模式创建的,建造者模式可以 方便用户创建复杂的对象

 

二.查看Bulider的构造方法

public Builder() {
this(Platform.get());
}

很简短,我们来一起看一下Platform.get()方法

private static final Platform PLATFORM = findPlatform();

static Platform get() {
return PLATFORM;
}

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) {
}
return new Platform();
}

这里面首先get方法返回的是PLATFORM,这是一个全局静态常量,从源代码可知最终调用的是findPlatform()方法

根据不同的平台判断提供不同的线程池,Class.forName运用了java反射机制

三.接下来查看一下build方法,看一下Retrofit是如何创建的

public Retrofit build() {
if (baseUrl == null) {     //强调了baseUrl不能为空
throw new IllegalStateException("Base URL required.");  //无效状态异常
}

okhttp3.Call.Factory callFactory = this.callFactory;   //如果需要对OkHttpClient进行设置,则可以构建OkHttpClient对象,然后调用callFactory方法将设置好的OkHttpClient传进去,
                                                                                    //如果callFactroy为空则,直接创建一个OkHttpClient
if (callFactory == null) {
callFactory = new OkHttpClient();
}

Executor callbackExecutor = this.callbackExecutor;       //线程回调到UI线程
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);    //将我们设置的Call适配器添加到列表中,比如RxJava的适配器
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));       //添加默认的Call适配器

// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);  //添加数据转换器  
 
//构建Retrofit  
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, 
callbackExecutor, validateEagerly);
}

这里讲一下 callbackExecutor回调执行器,这个是用于网络请求返回后回调到主线程的。我们知道,在利用OkHttp3进行网络请求时,我们需要手动回调到主线程,以便更新UI。那我们来看看这个默认的defaultCallbackExecutor是不是这样。

Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}

这一段代码表明,如果没有对callbackExecutor进行自定义设置,则在callbackExecutor为null时,调用platform里面的defaultCallbackExecutor方法

在看下面这段代码,实际上调用的是Android这个类的defaultCallbackExecutor方法,而这个方法返回的是MainThreadExecutor,它的作用就是利用handler将执行结果回调到主线程中。

(通过platform.get判断是安卓平台)

static class Android extends Platform {
@Override 
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override 
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());   //实例化的时候用Looper.getMainLooper()就表示放到主UI线程去处理。 
@Override public void execute(Runnable r) {
handler.post(r);       //发送到主线程
}
}
}

四create创建

创建好了Retrofit,那我们当然是要调用它的Api了,其实它的Api也就一个: T create(final Class service),就是这个方法。它的作用就是用动态代理模式,产生一个代理对象,可以用这个代理对象替我们完成网络请求,并返回结果。看看代码是怎么写的吧:

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 {
// 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<Object, Object> serviceMethod =(ServiceMethod<Object, Object>) loadServiceMethod(method);    // 这里还是封装method方法,并且处理对应的注解生成指定的请求头和请求体.
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);  // okHttpCall真正的请求实现类
return serviceMethod.callAdapter.adapt(okHttpCall);    // 返回对应封装了指定数据类型的Call  下面给出例子
}
});
}

1.

Utils.validateServiceInterface(service);
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}

判断service是否是接口类型,以及service接口是否继承了其他接口,service不是接口,或者继承了其他接口都会抛出非法参数异常

2.create方法返回了一个Proxy.newProxyInstance动态代理对象 ,它有三个参数:第一个是代理对象,第二个参数是调用的方法,第三个参数是方法的参数

最终调用的是InvocationHandler的invoke方法

3.例子:

HttpManger manger=new HttpManger();

public Observable<NewsBean<com.example.administrator.anew.Bean.ResultBean>> getNews(String type, String key){

ApiService apiService=manger.getRetrofit(manger.getOkhttp()).create(ApiService.class);

return apiService.getApp(type,key);//实际上这个是Observable<NewBean<EntryBean>>    返回对应封装了指定数据类型的call

}

 

4.精讲一下loadServiceMethod方法

ServiceMethod loadServiceMethod(Method method) {

2 ServiceMethod result;

3 synchronized (serviceMethodCache) {

4 result = serviceMethodCache.get(method);//Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>()

5 if (result == null) {

6 result = new ServiceMethod.Builder(this, method).build();

7 serviceMethodCache.put(method, result);

8 }

9 }

10 return result;

11 }

这里首先会从serviceMethodCache  查询传入的方法是否有缓存。如果有,就用缓存的ServiceMethod;如果没有,就创建一个,并加入serviceMethodCade缓存起来。

到这里本期开车已经抵达终点站,第一次写源码类型的文章,可能有一些不对的地方,欢迎留言,共同进步。

待续......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值