Android Retrofit源码分析(一边用一边侃)

不操千曲而后晓声,观千剑而后识器。这篇文章主要讲述Android Retrofit源码分析(一边用一边侃)相关的知识,希望能为你提供帮助。
这几天空余时间总是想着写点什么,所以紧跟着之前android盒子模型FlexBoxLayout之后有写下了这篇Retrofit源码分析使用篇。
前言:
Retrofit由于简单与出色的性能,使其安卓上最流行的HTTP Client库之一。
Android Studio开发相关配置如下:

compile "com.squareup.retrofit2:retrofit:2.0.2"

compile "com.squareup.retrofit2:converter-gson:2.0.2"

这里仅仅是简单的说明下使用,不会过多的讲解说明作用,原因就是类似使用文章百度可谓是一堆堆(杂乱无章)
OkHttpClient client = new OkHttpClient(); client.networkInterceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response response = chain.proceed(chain.request()); /*添加需要过滤的请求*/ return response; } });

上述代码代码只有在有需要过滤特殊的网络请求时才有必要,否则可以不用理睬,往下看。
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://api.nuuneoi.com/base/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build();

这里涉及Retrofit的创造和参数的构建,这里回答下上边说道的为什么在不需要进行相应的参数过滤的时候,可以不用指定对应的Client,让我看下源码内部实现:
1 /** 2* Create the {@link Retrofit} instance using the configured values. 3* < p> 4* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link 5* OkHttpClient} will be created and used. 6*/ 7public Retrofit build() { 8if (baseUrl == null) { 9throw new IllegalStateException("Base URL required."); 10} 11 12okhttp3.Call.Factory callFactory = this.callFactory; 13if (callFactory == null) { 14callFactory = new OkHttpClient(); 15} 16 17Executor callbackExecutor = this.callbackExecutor; 18if (callbackExecutor == null) { 19callbackExecutor = platform.defaultCallbackExecutor(); 20} 21 22// Make a defensive copy of the adapters and add the default Call adapter. 23List< CallAdapter.Factory> adapterFactories = new ArrayList< > (this.adapterFactories); 24adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); 25 26// Make a defensive copy of the converters. 27List< Converter.Factory> converterFactories = new ArrayList< > (this.converterFactories); 28 29return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, 30callbackExecutor, validateEagerly); 31}

这里是Retrofit内部builder构建类进行build时候执行的方法,这里稍稍关注下行12-15,判断是否callFactory是否为空,那么callFactory对象来自哪里哪?咱们继续深入源码。
/** * Specify a custom call factory for creating {@link Call} instances. * < p> * Note: Calling {@link #client} automatically sets this value. */ public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; }

这里是给callFactory对象赋值的地方,那我在看谁调用了这个方法。

/** * The HTTP client used for requests. * < p> * This is a convenience method for calling {@link #callFactory}. * < p> * Note: This method < b> does not< /b> make a defensive copy of {@code client}. Changes to its * settings will affect subsequent requests. Pass in a {@linkplain OkHttpClient#clone() cloned} * instance to prevent this if desired. */ public Builder client(OkHttpClient client) { return callFactory(checkNotNull(client, "client == null")); }

很显然这里就是我们在初始化Retrofit的时候添加OkHttpClient的地方。这也就是刚才说的为什么但咱们不需要过滤网络请求可以不添加OkHttpClient

这里需要大家稍微记下是ConverterFactory,他的作用是对返回的数据格式化。
这里之所以说道这块以防你需要调整json里面的一些格式,比如,Date Format。你可以创建一个Gson 对象并把它传递给GsonConverterFactory.create(),遇到类似问题可以参考如下处理方式
 
son gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd‘T‘HH:mm:ssZ") .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("") .addConverterFactory(GsonConverterFactory.create(gson)) .build();

 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
紧接着让我们跟着上边的简单使用来全面走进源码,一窥内部实现方式。
  1、这里需要优先记忆的几个对象声明如下:
callFactory:这个参数代表是实现了Call.Factory接口的类的实例,其实也就是OkHttpClient
converterFactories:返回数据格式化类,也就是GonsConverterFactory类
  adapterFactories:这个集合对象内部是CallAdapter.Factory接口实现类的实例对象

根据上述的简单使用我们了解到,Retrofit在创建的时候需要传入一个字节码文件,这里姑且不说这个字节码文件是类还是接口,咱们看下源码内部设计。
 
1 @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety. 2public < T> T create(final Class< T> service) { 3Utils.validateServiceInterface(service); 4if (validateEagerly) { 5eagerlyValidateMethods(service); 6} 7return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class< ?> [] { service }, 8new InvocationHandler() { 9private final Platform platform = Platform.get(); 10 11@Override public Object invoke(Object proxy, Method method, Object... args) 12throws Throwable { 13// If the method is a method from Object then defer to normal invocation. 14if (method.getDeclaringClass() == Object.class) { 15return method.invoke(this, args); 16} 17if (platform.isDefaultMethod(method)) { 18return platform.invokeDefaultMethod(method, service, proxy, args); 19} 20ServiceMethod serviceMethod = loadServiceMethod(method); 21OkHttpCall okHttpCall = new OkHttpCall< > (serviceMethod, args); 22return serviceMethod.callAdapter.adapt(okHttpCall); 23} 24}); 25}

 
大家注意下方法内部第3行,Utils.validateServiceInterface(service),这里直接翻译就是是否是有效的服务接口,看名字可能有些人会一下不是很明白,让我看下改方法实现。
1static < T> void validateServiceInterface(Class< T> service) { 2if (!service.isInterface()) { 3throw new IllegalArgumentException("API declarations must be interfaces."); 4} 5// Prevent API interfaces from extending other interfaces. This not only avoids a bug in 6// Android (http://b.android.com/58753) but it forces composition of API declarations which is 7// the recommended pattern. 8if (service.getInterfaces().length > 0) { 9throw new IllegalArgumentException("API interfaces must not extend other interfaces."); 10} 11}

 
直译代码行2,意思是传入的字节码文件是是否是接口,如果不是则抛出一个非法参数异常,这是其一。行8看到该接口是否继承自其它接口,也就是说该接口不允许采用继承的方式。到这里咱们总结了两点
Retrofit的Create方法传入的字节码文件要求如下:
必须是一个接口
该接口不能继承其他接口
 2、这里还是create方法的使用,那么接下来我们来看看他们是如何使用接口,完成一系列的网络请求的。
这里首先我们在回到刚才的Create方法中,看下Create方法对应的返回值
 
1 ...... 2 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class< ?> [] { service }, 3new InvocationHandler() { 4private final Platform platform = Platform.get(); 5 6@Override public Object invoke(Object proxy, Method method, Object... args) 7throws Throwable { 8// If the method is a method from Object then defer to normal invocation. 9if (method.getDeclaringClass() == Object.class) { 10return method.invoke(this, args); 11} 12if (platform.isDefaultMethod(method)) { 13return platform.invokeDefaultMethod(method, service, proxy, args); 14} 15ServiceMethod serviceMethod = loadServiceMethod(method); 16OkHttpCall okHttpCall = new OkHttpCall< > (serviceMethod, args); 17return serviceMethod.callAdapter.adapt(okHttpCall); 18} 19}); 20 ......

 
这里使用到java中高级部分篇章java的动态代理,简单点来说也就是当你调用接口中对应的方法会优先调用InvocationHandler中的invoke方法,有不是很明白的童鞋可行百度了解这块技术,这里就不在深入介绍。
知道动态代理的基本流程,让我们看下invoke方法内部究竟是如何工作的。
2.1、行4,这里根据不同的平台返回不同的Platform platform = Platform.get()对象
【Android Retrofit源码分析(一边用一边侃)】2.2、行9-11,这里是判断调用的方式是否是Object里的方法,如果是则直接调用不做处理.
2.3、行12-14,这里仅仅是java8才会使用
2.4、行15,这里还是封装method方法,并且处理对应的注解生成指定的请求头和请求体.
2.5、行16,okHttpCall真正的请求实现类

2.6、行17,返回对应封装了指定数据类型的Call
 
2.1、精讲说明
1private static final Platform PLATFORM = findPlatform(); 2 3static Platform get() { 4return PLATFORM; 5} 6 7private static Platform findPlatform() { 8try { 9Class.forName("android.os.Build"); 10if (Build.VERSION.SDK_INT != 0) { 11return new Android(); 12} 13} catch (ClassNotFoundException ignored) { 14} 15try { 16Class.forName("java.util.Optional"); 17return new Java8(); 18} catch (ClassNotFoundException ignored) { 19} 20try { 21Class.forName("org.robovm.apple.foundation.NSObject"); 22return new ios(); 23} catch (ClassNotFoundException ignored) { 24} 25return new Platform(); 26}

2.1.1、这里调用Platform的静态方法get(),然后调用方法findPlatform()
2.1.2、方法findPlatform()根据不同的平台返回不同的对象,这里咱们使用的Android,所以返回的是Android对象
Android类对象继承Platform类,源码如下:
1static class Android extends Platform { 2@Override public Executor defaultCallbackExecutor() { 3return new MainThreadExecutor(); 4} 5 6@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { 7return new ExecutorCallAdapterFactory(callbackExecutor); 8} 9 10static class MainThreadExecutor implements Executor { 11private final Handler handler = new Handler(Looper.getMainLooper()); 12 13@Override public void execute(Runnable r) { 14handler.post(r); 15} 16} 17}

如上代码可以知道,
1、Android继承自类Platform,重载了Platform方法defaultCallbackExecutor和defaultCallAdapterFactory,方法defaultCallbackExecutor返回一个MainThreadExecutor对象,方法defaultCallAdapterFactory返回了一个对象ExecutorCallAdapterFactory
2、声明静态内部类MainThreadExecutor实现了接口Executor,同时初始化了一个Handler对象。

2.2、精讲说明< 判断调用的方式是否是Object里的方法,如果是则直接调用不做处理.>
由于不涉及Retrofit的相关操作,这里不再进行说明。
2.3、精讲说明< 这里仅仅是java8才会使用>
为什么这么说那,关键在于代码platform.isDefaultMethod(method),所以想说明白这个问题我们还是需要在进一步看下方法isDefaultMethod,当然前边我说道platform返回的是Android,所以这里先从类Android看。上边说道类Platform重载了Platform方法defaultCallbackExecutor和defaultCallAdapterFactory,所以这里仅仅需要看下platform类对该方法的处理即可。
boolean isDefaultMethod(Method method) { return false; }

默认返回是false,很显然Android平台并不会进入逻辑处理,那么既然说道java8才会使用那么必然java类重载了该方法,深入源码我们看下。
static class Java8 extends Platform { @Override boolean isDefaultMethod(Method method) { return method.isDefault(); } }

正如我们想象的那样。
 
2.4、精讲说明< 这里还是封装method方法,并且处理对应的注解生成指定的请求头和请求体.>
这里我们先跟着代码一起往下看loadServiceMethod(method)
1 ServiceMethod loadServiceMethod(Method method) { 2ServiceMethod result; 3synchronized (serviceMethodCache) { 4result = serviceMethodCache.get(method); //Map< Method, ServiceMethod> serviceMethodCache = new LinkedHashMap< > () 5if (result == null) { 6result = new ServiceMethod.Builder(this, method).build(); 7serviceMethodCache.put(method, result); 8} 9} 10return result; 11}

这里对method和对应的ServiceMethod做了缓存,这里优先判断缓存,如果不存在则去new一个ServiceMethod对象。继续看ServiceMethod对象创建的过程。
类Builder构造器
1 public Builder(Retrofit retrofit, Method method) { 2this.retrofit = retrofit; 3this.method = method; 4this.methodAnnotations = method.getAnnotations(); 5this.parameterTypes = method.getGenericParameterTypes(); 6this.parameterAnnotationsArray = method.getParameterAnnotations(); 7}

 
待续
 
 
 
 
 
 
 
 
 





    推荐阅读