站在巨人的肩膀上 -- Retrofit源码解析

Posted 巨头之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了站在巨人的肩膀上 -- Retrofit源码解析相关的知识,希望对你有一定的参考价值。

上一篇 站在巨人的肩膀上 – Retrofit源码解析(一) 主要是从Retrofit使用的基本API角度,去理清源码中大致的流程,可以说Retrofit是对OkHttp框架做了非常完美的封装,使用了大量的设计模式,使得Retrofit成为了一个简单易上手的网络请求框架. 这一篇主要解决上一篇留下来的疑问.

Retrofit源码基于版本2.4.0

1.ServiceMethod.Builder类的build函数,调用createCallAdapter函数是怎么获取到callAdapter的?

从createCallAdapter函数出发,调用到Retrofit类的callAdapter函数


	private CallAdapter<T, R> createCallAdapter() 
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) 
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      
      if (returnType == void.class) 
        throw methodError("Service methods cannot return void.");
      
      Annotation[] annotations = method.getAnnotations();
      try 
        //noinspection unchecked
        //遍历 存放网络请求适配器工厂的集合callAdapterFactories,找到合适的网络请求适配器工厂并返回
        return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
       catch (RuntimeException e)  // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      
    

callAdapter函数调用nextCallAdapter函数,主要遍历callAdapterFactories这个存放网络请求适配器工厂的集合,获取跟网络请求函数返回值Call<List< Contributor>>相关的网络请求适配器工厂,那callAdapterFactories是在哪里存入适配器工厂? 存入了哪些适配器工厂?


	public final class Retrofit 

		public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) 
		    return nextCallAdapter(null, returnType, annotations);
		  

		//
		public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) 
		    checkNotNull(returnType, "returnType == null");
		    checkNotNull(annotations, "annotations == null");
		
		    //遍历存放网络请求适配器工厂的集合callAdapterFactories,找到合适的网络请求适配器工厂调用其get函数并返回CallAdapter实例
		    int start = callAdapterFactories.indexOf(skipPast) + 1;
		    for (int i = start, count = callAdapterFactories.size(); i < count; i++) 
		      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
		      if (adapter != null) 
		        return adapter;
		      
		    		

			...省略无关代码
		
	
	

callAdapterFactories是在Retrofit的构造函数中赋值的, 而Retrofit是通过Build模式创建的, 看Retrofit.Builder类的build函数


	public final class Retrofit 
		public static final class Builder 
			
			public Retrofit build() 

				...省略部分无关代码

				List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
		        //将MainThreadExecutor装载进ExecutorCallAdapterFactory工厂实例里,并将工厂实例添加进 网络请求适配器工厂的集合里
		        callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

				...省略部分无关代码

				 //Collections.unmodifiableList()函数是将集合转化成只读的
				return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);	
			
	
			//添加网络请求适配器
			public Builder addCallAdapterFactory(CallAdapter.Factory factory) 
		      callAdapterFactories.add(checkNotNull(factory, "factory == null"));
		      return this;
		    
		
	

看到callAdapterFactories存入开发者自行添加进去的网络请求适配器工厂,还存入该平台默认的网络请求适配器工厂,此处是android平台,对应的网络请求适配器工厂为ExecutorCallAdapterFactory, 还记得我们在创建Retrofit时调用了.addCallAdapterFactory(RxJavaCallAdapterFactory.create()),所以此处自行添加的网络请求适配器工厂是RxJavaCallAdapterFactory.

现在也就找到callAdapterFactories是在Retrofit.Builder的build函数中存入适配器工厂的,存入了两个适配器工厂,分别是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory.

那上面说的 “获取跟网络请求函数返回值Call<List< Contributor>>相关的网络请求适配器工厂”,获取到的就应该是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory其中之一

在Retrofit类的nextCallAdapter函数中,通过遍历callAdapterFactories集合,取出网络请求适配器工厂并调用自身的get函数,我们看下ExecutorCallAdapterFactory和RxJavaCallAdapterFactory这两个类的get函数


	public final class RxJavaCallAdapterFactory extends CallAdapter.Factory 

	  @Override
	  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) 
	    Class<?> rawType = getRawType(returnType);
	    boolean isSingle = rawType == Single.class;
	    boolean isCompletable = rawType == Completable.class;

		//请求函数的返回值必须是 Observable或Single或Completable
    	//否则返回null
	    if (rawType != Observable.class && !isSingle && !isCompletable) 
	      return null;
	    
	
	    if (isCompletable) 
	      return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
	    
	  
	

由于我们在上篇文章中写的网络请求函数的返回值是 “Call<List< Contributor>>”, 那RxJavaCallAdapterFactory的get函数中getRawType(returnType)拿到的Class类型就是Call,不满足判断条件, 所以此处会返回null, 因此不是RxJavaCallAdapterFactory


	final class ExecutorCallAdapterFactory extends CallAdapter.Factory 

	  @Override
	  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) 
	    if (getRawType(returnType) != Call.class) 
	      return null;
	    
	    final Type responseType = Utils.getCallResponseType(returnType);
	    return new CallAdapter<Object, Call<?>>() 
	      @Override public Type responseType() 
	        return responseType;
	      
	
	      //这里传入的call = OkHttpCall实例,callbackExecutor = MainThreadExecutor实例
	      @Override public Call<Object> adapt(Call<Object> call) 
	        return new ExecutorCallbackCall<>(callbackExecutor, call);
	      
	    ;
	  
	

ExecutorCallAdapterFactory类的get函数中,通过getRawType获取到的是Call类型,满足条件,那么满足适配器工厂条件的就是ExecutorCallAdapterFactory类,其get函数中创建了CallAdapter的匿名内部类并返回,那此处的匿名内部类实例就是ServiceMethod.Builder类的createCallAdapter函数中retrofit.callAdapter( )获取到的值,也就是在ServiceMethod.Builder类的build函数调用createCallAdapter函数返回的就是这个匿名内部类

2.ServiceMethod.Builder类的build函数,调用createResponseConverter函数是怎么生成responseConverter的?

这里生成的responseConverter的代码流程跟上面1类似

从createResponseConverter函数出发,调用到Retrofit类的nextResponseBodyConverter函数


	private Converter<ResponseBody, T> createResponseConverter() 
      Annotation[] annotations = method.getAnnotations();
      try 
        //遍历 存放数据转换器工厂的集合converterFactories,找到合适的数据转换器工厂并返回
        return retrofit.responseBodyConverter(responseType, annotations);
       catch (RuntimeException e)  // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      
    

	public final class Retrofit 

		 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) 
    		return nextResponseBodyConverter(null, type, annotations);
  		

		public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) 
		    checkNotNull(type, "type == null");
		    checkNotNull(annotations, "annotations == null");
		
		    //遍历 存放数据转换器工厂的集合converterFactories,找到合适的数据转换器工厂并返回
		    int start = converterFactories.indexOf(skipPast) + 1;
		    for (int i = start, count = converterFactories.size(); i < count; i++) 
		      Converter<ResponseBody, ?> converter =
		          converterFactories.get(i).responseBodyConverter(type, annotations, this);
		      if (converter != null) 
		        //noinspection unchecked
		        return (Converter<ResponseBody, T>) converter;
		      
	   		
			
				...省略无关代码
	   
	

在nextResponseBodyConverter函数中,主要遍历converterFactories这个存放数据转换器工厂的集合,获取跟网络请求函数返回值Call<List< Contributor>>相关的数据转换器工厂,那converterFactories在哪里存入数据转换器工厂? 存入了哪些数据转换器工厂?

converterFactories是在Retrofit的构造函数中赋值的, 而Retrofit是通过Build模式创建的, 看Retrofit.Builder类的build函数


	public final class Retrofit 
		public static final class Builder 

			public Retrofit build() 

			   //...省略无关代码
							
		      List<Converter.Factory> converterFactories =
		          new ArrayList<>(1 + this.converterFactories.size());
		
		      //将默认的数据转换器装载进工厂实例里,添加数据转换器工厂进集合里
		      converterFactories.add(new BuiltInConverters());
		      converterFactories.addAll(this.converterFactories);

			  //Collections.unmodifiableList()函数是将集合转化成只读的
           		return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);	
			
			

			//添加数据转化器工厂
			public Builder addConverterFactory(Converter.Factory factory) 
		      converterFactories.add(checkNotNull(factory, "factory == null"));
		      return this;
		    

		
	

看到converterFactories存入开发者自行添加进去的数据转换器工厂,还存入该平台默认的数据转换器工厂BuiltInConverters类的实例, 还记得我们在创建Retrofit时调用了.addConverterFactory(GsonConverterFactory.create()),所以此处自行添加的数据转换器工厂是GsonConverterFactory.

现在也就找到converterFactories是在Retrofit.Builder的build函数中存入转换器工厂的,存入了两个数据转换器工厂,分别是BuiltInConverters和GsonConverterFactory.

那上面说的 “获取跟网络请求函数返回值Call<List< Contributor>>相关的数据转换器工厂”,获取到的就应该是BuiltInConverters和GsonConverterFactory其中之一

在Retrofit类的nextResponseBodyConverter函数中,通过遍历converterFactories集合,取出数据转换器工厂并调用自身的responseBodyConverter函数,我们看下BuiltInConverters和GsonConverterFactory这两个类的responseBodyConverter函数


	final class BuiltInConverters extends Converter.Factory 

		  @Override
		  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
		      Retrofit retrofit) 
		    if (type == ResponseBody.class) 
		      return Utils.isAnnotationPresent(annotations, Streaming.class)
		          ? StreamingResponseBodyConverter.INSTANCE
		          : BufferingResponseBodyConverter.INSTANCE;
		    
		    if (type == Void.class) 
		      return VoidResponseBodyConverter.INSTANCE;
		    
		    return null;
		  
	

此处的type就是根据网络请求函数返回值Call<List< Contributor>> 获取到的响应数据类型,即type 等于java.util.List<com.example.retrofit.SimpleService$Contributor>,所以BuiltInConverters类的responseBodyConverter函数经过判断会返回null,显然不是这个系统默认的数据转换器工厂


	public final class GsonConverterFactory extends Converter.Factory 

		  @Override
		  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
		      Retrofit retrofit) 
		    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
		    return new GsonResponseBodyConverter<>(gson, adapter);
		  
		
	

根据type等于java.util.List<com.example.retrofit.SimpleService$Contributor>,返回的应该是GsonConverterFactory这个数据转换器工厂,在其responseBodyConverter函数中返回GsonResponseBodyConverter类的实例,GsonResponseBodyConverter是负责将响应数据转化为开发者指定的Java类

因此,在ServiceMethod.Builder类的build函数调用createResponseConverter函数返回的就是GsonResponseBodyConverter类的实例, 即responseConverter就是GsonResponseBodyConverter类的实例

3.OkHttpCall类的createRawCall函数中的call的具体实现类是哪个? 内部怎么实现的?


	final class OkHttpCall<T> implements Call<T> 

		private okhttp3.Call createRawCall() throws IOException 
		   
		    okhttp3.Call call = serviceMethod.toCall(args);
		    if (call == null) 
		      throw new NullPointerException("Call.Factory returned null.");
		    
		    return call;
		
	

createRawCall函数中的call是通过调用ServiceMethod类的toCall函数生成的,看toCall函数


	final class ServiceMethod<R, T> 
		
		okhttp3.Call toCall(@Nullable Object... args) throws IOException 

		   	//...省略无关代码

		    //callFactory = OkHttpClient,该OkHttpClient是在Retrofit.Buidler的build函数中进行设置值的
		    //所以这里的okhttp3.Call来源于OkHttp.RealCall类的实例
		    return callFactory.newCall(requestBuilder.build());
		  
	

callFactory是在ServiceMethod的构造函数中被赋值,其值来自于Retrofit类,回到Retrofit.Builder类的build函数中


	public final class Retrofit 
		public static final class Builder 

			public Retrofit build() 
				//开发者是否传入OkHttpClient实例,未传入则创建
			      okhttp3.Call.Factory callFactory = this.callFactory;
			      if (callFactory == null) 
			        callFactory = new OkHttpClient();
			      

				  return new Retrofit(callFactory, baseUrl, 
					unmodifiableList(converterFactories),
          			unmodifiableList(callAdapterFactories), callbackExecutor, 
					validateEagerly);
			

			
			public Builder callFactory(okhttp3.Call.Factory factory) 
		      this.callFactory = checkNotNull(factory, "factory == null");
		      return this;
		    
		
	

callFactory变量就是在此处被初始化的, 在创建Retrofit时,如果开发者未传入okhttp3.Call.Factory类的实现实例, 则会赋予系统默认的OkHttpClient,所以callFactory实际就是OkHttpClient实例.

接着回到ServiceMethod类的toCall函数,callFactory.newCall() 不就等于OkHttpClient.newCall(), 对OkHttp框架熟悉的话,是不是觉得似曾相似


	public class OkHttpClient implements Cloneable, Factory, okhttp3.WebSocket.Factory 

		public Call newCall(Request request) 
	        return RealCall.newRealCall(this, request, false);
	    
	

那么OkHttpCall类的createRawCall函数中的call也就是此处生成的RealCall实例. 从这可以看出,OkHttpCall类是通过OkHttp框架来发起异步/同步的请求

4.OkHttpCall类的enqueue函数和execute函数中调用的parseResponse(rawResponse)函数,内部是怎么解析响应数据的?


	final class OkHttpCall<T> implements Call<T> 

		Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException 
	    ResponseBody rawBody = rawResponse.body();
	
	    // Remove the body's source (the only stateful object) so we can pass the response along.
	    rawResponse = rawResponse.newBuilder()
	        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
	        .build();
	    //根据服务端返回的响应码进行判断并处理
	    int code = rawResponse.code();
	    if (code < 200 || code >= 300) 
	      try 
	        // Buffer the entire body to avoid future I/O.
	        ResponseBody bufferedBody = Utils.buffer(rawBody);
	        return Response.error(bufferedBody, rawResponse);
	       finally 
	        rawBody.close();
	      
	    
	
	    if (code == 204 || code == 205) 
	      rawBody.close();
	      return Response.success(null, rawResponse);
	    
	
	    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
	    try 
	      //将响应数据转化为 网络请求函数中定义的返回类型
	      T body = serviceMethod.toResponse(catchingBody);
	      return Response.success(body, rawResponse);
	     catch (RuntimeException e) 
	      // If the underlying source threw an exception, propagate that rather than indicating it was
	      // a runtime exception.
	      catchingBody.throwIfCaught();
	      throw e;
	    
	  
	

看上面的代码,核心在serviceMethod.toResponse这一句, 接着往下看


	final class ServiceMethod<R, T> 

		R toResponse(ResponseBody body) throws IOException 
		    return responseConverter.convert(body);
		
	

这里的responseConverter不就是上面第2个问题中获取到的GsonResponseBodyConverter类的实例,而GsonResponseBodyConverter内部是用了Gson框架来解析数据.


	final class<

以上是关于站在巨人的肩膀上 -- Retrofit源码解析的主要内容,如果未能解决你的问题,请参考以下文章

站在巨人的肩膀上 -- Retrofit源码解析

世界最好的字体引擎,泰山FreeType,开源:我们站在巨人的肩膀上

android开发利器--站在巨人肩膀上前行

软件工程——站在巨人的肩膀上抱团取暖

openResty,站在巨人的肩膀上

小游戏“跳一跳”——站在巨人的肩膀上,用技术为自己助力