开车:
用了这么久的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缓存起来。
到这里本期开车已经抵达终点站,第一次写源码类型的文章,可能有一些不对的地方,欢迎留言,共同进步。
待续......