Retrofit2源码解析(一)

xiaoxiao2022-06-11  69

开车:

用了这么久的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缓存起来。

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

待续......

转载请注明原文地址: https://www.6miu.com/read-4931397.html

最新回复(0)