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 GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
	  private final Gson gson;
	  private final TypeAdapter<T> adapter;
	
	  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
	    this.gson = gson;
	    this.adapter = adapter;
	  }
	
	  @Override public T convert(ResponseBody value) throws IOException {
	    JsonReader jsonReader = gson.newJsonReader(value.charStream());
	    try {
	      T result = adapter.read(jsonReader);
	      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
	        throw new JsonIOException("JSON document was not fully consumed.");
	      }
	      return result;
	    } finally {
	      value.close();
	    }
	  }
	}

5.retrofit類create函數中的serviceMethod.adapt是怎麼返回OkHttpCall類的,內部是怎麼實現的?


	public final class Retrofit {
		 public static final class Builder {

			public <T> T create(final Class<T> service) {

		    //檢查網絡請求接口類是不是接口,有沒繼承其他接口 等
		    Utils.validateServiceInterface(service);
		    //判斷是否需要提前緩存ServiceMethod對象, validateEagerly默認爲false
		    if (validateEagerly) {
		      eagerlyValidateMethods(service);
		    }
		    // 使用動態代理模式拿到 網絡請求接口類的函數的註解、函數參數、函數返回值等相關信息
		    // 返回接口調用實例Call,其實這個Call是ExecutorCallbackCall類(Retrofit的Call的實現類)的實例,在後面的代碼中能看到
		    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接口負責存 網絡請求接口類的函數的註解、函數參數、函數返回值等相關信息
		              ServiceMethod<Object, Object> serviceMethod =
		                (ServiceMethod<Object, Object>) loadServiceMethod(method);
		            //OkHttpCall是對Retrofit.Call的實現,實際該類主要用到OkHttp.Call(rawCall這個變量) 來進行enqueue、execute請求
		            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
		            //這裏實際上返回的是ExecutorCallbackCall類(Retrofit的Call的實現類)的實例,看後面的代碼
		            return serviceMethod.adapt(okHttpCall);
		          }
		        });
		  }
		 }
	}

跟進去ServiceMethod類的adapt函數


	final class ServiceMethod<R, T> {
		T adapt(Call<R> call) {
	    	return callAdapter.adapt(call);
	    }
	}

adapt函數是調用了callAdapter對象的adapt函數,有沒覺得這個callAdapter蠻熟悉的,這不就是上面第1點的callAdapter,它的值就是ExecutorCallAdapterFactory類中get函數中創建的匿名內部類


	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);
		      }
		    };
		  }
	}

那麼retrofit類create函數中的serviceMethod.adapt()拿到的就是此處的ExecutorCallbackCall的實例,那ExecutorCallbackCall這個類又有什麼用呢? 這裏多提一個問題,ExecutorCallbackCall是Retrofit框架中很重要的一個類,往下看

6.從上面第5點知道retrofit類create函數中的serviceMethod.adapt()返回的是ExecutorCallbackCall類,這個類有什麼作用?


	final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
		static final class ExecutorCallbackCall<T> implements Call<T> {

			final Executor callbackExecutor;
		    final Call<T> delegate;
		    //這裏傳入的delegate = OkHttpCall實例,callbackExecutor = MainThreadExecutor實例
		    ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
		      this.callbackExecutor = callbackExecutor;
		      this.delegate = delegate;
		    }
		
		    @Override public void enqueue(final Callback<T> callback) {
		      checkNotNull(callback, "callback == null");
		      //這裏的delegate = OkHttpCall實例
		      //OkHttpCall是對Retrofit.Call的實現,實際該類主要用到OkHttp.Call(rawCall這個變量) 來進行enqueue、execute請求
		      delegate.enqueue(new Callback<T>() {
		        @Override public void onResponse(Call<T> call, final Response<T> response) {
		          //callbackExecutor = MainThreadExecutor, 主要從子線程切換到主線程並返回響應結果
		          callbackExecutor.execute(new Runnable() {
		            @Override public void run() {
		              if (delegate.isCanceled()) {
		                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
		                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
		              } else {
		                callback.onResponse(ExecutorCallbackCall.this, response);
		              }
		            }
		          });
		        }
		
		        @Override public void onFailure(Call<T> call, final Throwable t) {
		          callbackExecutor.execute(new Runnable() {
		            @Override public void run() {
		              callback.onFailure(ExecutorCallbackCall.this, t);
		            }
		          });
		        }
		      });
		    }
		
		    @Override public boolean isExecuted() {
		      return delegate.isExecuted();
		    }
		
		    @Override public Response<T> execute() throws IOException {
		      //這裏的delegate = OkHttpCall實例
		      return delegate.execute();
		    }
		
		    @Override public void cancel() {
		      delegate.cancel();
		    }
		
		    @Override public boolean isCanceled() {
		      return delegate.isCanceled();
		    }
		
		    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
		    @Override public Call<T> clone() {
		      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
		    }
		
		    @Override public Request request() {
		      return delegate.request();
		    }
		  
		}
	}

看上面的代碼和註釋,ExecutorCallAdapterFactory類主要做了兩件事

  • 結合代碼和註釋,調用OkHttpCall類來發起請求,從上面第3點了解到,OkHttpCall類是通過OkHttp框架來發起異步/同步的請求,因此ExecutorCallbackCall類間接調用了OkHttp框架來發起異步/同步的請求

  • MainThreadExecutor把子線程切換到主線程, 將請求OkHttp框架返回的服務端響應數據回調返回

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章