在上一篇okhttp源碼解析(執行流程)的文章中,已經對okhttp
的基本執行流程作了一個較爲詳細的探究。本篇文章將對Android
開發中另外一個經常使用的網絡請求框架Retrofit
作一個源碼分析,有關Retrofit
的相關介紹在這裏就不作贅述,咱們只對其執行過程以及其中涉及到的知識點進行相關分析。 html
在進行有關Retrofit
探究以前,須要知道兩個知識點:註解和動態代理。之因此須要對這兩個知識點有所準備,是由於它們在Retrofit
的源碼中有所涉及,因此但願你們可以有所理解。因爲今天的重點是關Retrofit
,因此我針對這兩個知識點爲你們準備了幾文章:java
Java註解深刻淺出
你真的徹底瞭解Java動態代理嗎?看這篇就夠了
Java動態代理
10分鐘看懂動態代理設計模式
android
Retrofit
的請求註解的使用這裏就再也不作詳細介紹,這裏爲小夥伴本準備了一篇這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解),若是不熟悉的小夥伴,請提早看一下。json
使用以前須要添加如下依賴:設計模式
implementation 'com.squareup.retrofit2:retrofit:2.6.2' implementation 'com.squareup.retrofit2:converter-gson:2.6.2' 複製代碼
關於後面兩個依賴,下文會給出解釋。數組
public class Bean { private int errorCode; private String errorMsg; private List<DataBean> data; public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public String getErrorMsg() { return errorMsg; } public void setErrorMsg(String errorMsg) { this.errorMsg = errorMsg; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } public static class DataBean { private int courseId; private int id; private String name; private int order; private int parentChapterId; private boolean userControlSetTop; private int visible; private List<?> children; public int getCourseId() { return courseId; } public void setCourseId(int courseId) { this.courseId = courseId; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public int getParentChapterId() { return parentChapterId; } public void setParentChapterId(int parentChapterId) { this.parentChapterId = parentChapterId; } public boolean isUserControlSetTop() { return userControlSetTop; } public void setUserControlSetTop(boolean userControlSetTop) { this.userControlSetTop = userControlSetTop; } public int getVisible() { return visible; } public void setVisible(int visible) { this.visible = visible; } public List<?> getChildren() { return children; } public void setChildren(List<?> children) { this.children = children; } @Override public String toString() { return "name:" + name; } } } 複製代碼
爲了接收到數據以後容易展現,重寫了toString
方法。緩存
public interface ServiceApi { @GET("wxarticle/chapters/json") Call<Bean> getWxArtical(); } 複製代碼
這裏使用了鴻洋的wanandroid開放API,標示感謝。安全
這裏爲了表示的更清楚,因此在兩個請求方法裏面各建立了一個Retrofit
對象,在實際的開發中建立一個就好了。markdown
// 同步請求 public void execute() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.wanandroid.com") .addConverterFactory(GsonConverterFactory.create()) .build(); ServiceApi serviceApi = retrofit.create(ServiceApi.class); final Call<Bean> officialAccounts = serviceApi.getOfficialAccounts(); new Thread() { @Override public void run() { try { Response<Bean> response = officialAccounts.clone().execute(); for (int i = 0; i < response.body().getData().size(); i++) { Log.i("retrofit", "execute: " + response.body().getData().get(i).toString()); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } 複製代碼
// 異步請求 public void enqueue() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.wanandroid.com") .addConverterFactory(GsonConverterFactory.create()) .build(); ServiceApi serviceApi = retrofit.create(ServiceApi.class); Call<Bean> officialAccounts = serviceApi.getOfficialAccounts(); officialAccounts.clone().enqueue(new Callback<Bean>() { @Override public void onResponse(Call<Bean> call, Response<Bean> response) { for (int i = 0; i < response.body().getData().size(); i++) { Log.i("retrofit", "enqueue: " + response.body().getData().get(i).toString()); } } @Override public void onFailure(Call<Bean> call, Throwable t) { } }); } 複製代碼
看一下請求結果: 網絡
建立Retrofit
時,咱們調用了new Retrofit.Builder()
方法:
public final class Retrofit { //網絡請求緩存,如:請求方法、請求頭、請求體,各類適配器等 private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); final okhttp3.Call.Factory callFactory; final HttpUrl baseUrl; final List<Converter.Factory> converterFactories; final List<CallAdapter.Factory> callAdapterFactories; final @Nullable Executor callbackExecutor; final boolean validateEagerly; Retrofit(okhttp3.Call.Factory callFactory , HttpUrl baseUrl ,List<Converter.Factory> converterFactories , List<CallAdapter.Factory> callAdapterFactories ,@Nullable Executor callbackExecutor , boolean validateEagerly) { this.callFactory = callFactory; this.baseUrl = baseUrl; this.converterFactories = converterFactories; this.callAdapterFactories = callAdapterFactories; this.callbackExecutor = callbackExecutor; this.validateEagerly = validateEagerly; } ... public static final class Builder { //平臺信息 private final Platform platform; //okhttp3請求工廠,默認是okhttp private @Nullable okhttp3.Call.Factory callFactory; //基礎請求地址 private @Nullable HttpUrl baseUrl; //轉換器集合 private final List<Converter.Factory> converterFactories = new ArrayList<>(); //請求適配器集合 private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); //執行異步回調的線程切換 private @Nullable Executor callbackExecutor; //是否提早解析方法註解標識 private boolean validateEagerly; public Builder() { this(Platform.get()); } Builder(Platform platform) { this.platform = platform; } Builder(Retrofit retrofit) { platform = Platform.get(); callFactory = retrofit.callFactory; baseUrl = retrofit.baseUrl; // Do not add the default BuiltIntConverters and platform-aware converters added by build(). for (int i = 1, size = retrofit.converterFactories.size() - platform.defaultConverterFactoriesSize(); i < size; i++) { converterFactories.add(retrofit.converterFactories.get(i)); } // Do not add the default, platform-aware call adapters added by build(). for (int i = 0, size = retrofit.callAdapterFactories.size() - platform.defaultCallAdapterFactoriesSize(); i < size; i++) { callAdapterFactories.add(retrofit.callAdapterFactories.get(i)); } callbackExecutor = retrofit.callbackExecutor; validateEagerly = retrofit.validateEagerly; } public Builder baseUrl(String baseUrl) { //判斷傳入的baseUrl是否爲null checkNotNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl)); } public Builder baseUrl(HttpUrl baseUrl) { //再一次判斷baseUrl是否爲null checkNotNull(baseUrl, "baseUrl == null"); List<String> pathSegments = baseUrl.pathSegments(); // 判斷baseUrl是否以'/'結尾,若是不是直接拋出異常 if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; } public Builder addConverterFactory(Converter.Factory factory) { converterFactories.add(checkNotNull(factory, "factory == null")); return this; } ... public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } } } 複製代碼
從上面的代碼咱們能夠看出,經過建立Retrofit.Builder
對象運用Builder
設計模式鏈式調用爲Retrofit.Builder
中的屬性進行賦值,調用build
方法時,將這些屬性賦值給一個Retrofit
對象,最後將這個Retrofit
對象返回。咱們看一下這裏面的屬性都是什麼意思。
在Retrofit類的內部會首先建立一個集合:
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); 複製代碼
這個集合的Key
是一個Mehtod
對象,Value
是與Key
相對應的ServiceMethod
對象。ServiceMethod
對象是根據Method
解析以後得到,這裏麪包含了Method
的方法註解、參數註解等一些列屬性。咱們從集合的名字就能看出來,這裏面是將Method
和對應ServiceMethod
進行緩存的集合,這種方法咱們在EventBus
源碼解析的時候就遇到過。這樣作的目的就是爲了加快運行速度,咱們在從此的開發中也能加以借鑑並運用。有關Method
和ServiceMethod
都會在下文中進行講解,這裏若是不知道是什麼意思也不要緊。
這個對象是Retrofit.Builder
對象中進行定義的。
public static final class Builder { private final Platform platform; ... Builder(Retrofit retrofit) { platform = Platform.get(); } ... } class Platform { private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } private static Platform findPlatform() { try { Class.forName("android.os.Build"); // 若是是Android平臺 if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { // 若是是Java平臺 Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); } ... } 複製代碼
在這裏咱們能夠看到這裏會根據不一樣的平臺信息返回對應的Platform
對象,分別是Android
和Java8
,重點分析一下Android
。
static class Android extends Platform { // 一、判斷方法是不是默認方法,所謂默認方法是指是不是Object類中已經定義的方法 // 若是是就返回true,不然返回false @IgnoreJRERequirement // Guarded by API check. @Override boolean isDefaultMethod(Method method) { if (Build.VERSION.SDK_INT < 24) { return false; } return method.isDefault(); } @Override public Executor defaultCallbackExecutor() { // 二、獲取一個Executor對象,這個對象表明了回調執行器 return new MainThreadExecutor(); } // 三、得到Android版本下默認的網絡適配器集合 @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories( @Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); // 默認的請求適配器 DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor); // 若是Android系統版本大於24,則會返回一個CompletableFutureCallAdapterFactory和DefaultCallAdapterFactory組成的集合。 // 不然返回只有DefaultCallAdapterFactory對象的集合 return Build.VERSION.SDK_INT >= 24 ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory) : singletonList(executorFactory); } @Override int defaultCallAdapterFactoriesSize() { return Build.VERSION.SDK_INT >= 24 ? 2 : 1; } // 四、獲取Android版本下默認的轉換器集合 @Override List<? extends Converter.Factory> defaultConverterFactories() { // 若是Android系統版本大於24,則會返回只有CompletableFutureCallAdapterFactory對象的集合 // 不然返回一個長度爲0的集合 return Build.VERSION.SDK_INT >= 24 ? singletonList(OptionalConverterFactory.INSTANCE) : Collections.<Converter.Factory>emptyList(); } @Override int defaultConverterFactoriesSize() { return Build.VERSION.SDK_INT >= 24 ? 1 : 0; } // 2.1 這裏返回的是Android主線程的回調 // 也就是說當網絡請求完成後會回調到Android主線程中去,這也是Retrofit和OkHttp的不一樣點之一 static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } } 複製代碼
在Android
平臺裏面咱們關注四點:
一、判斷傳入的
Method
對象是不是默認方法
二、獲取執行回調器,這裏默認的是將網絡請求結果回調到Android
主線程中。
三、得到Android
版本下默認的網絡適配器集合,這裏會根據Android
版本號進行返回。
四、獲取Android
版本下默認的轉換器集合,它也是會根據Android
版本號進行返回。
這裏有必要跟你們提早說一下,有關請求適配器(CallAdapter.Factory
)和轉換器(Converter.Factory
)會在下面的文章中給出,這裏先留一個印象。
咱們從單詞的表面意思能夠知道這個是請求工廠類,這個請求工廠類okhttp3
的Call
類型,這也說明了Retrofit
是基於okhttp
進行封裝的。定義callFactory
對象咱們能夠調用Retrofit.Builder.callFactory
方法進行設置,在Retrofit.Builder.build
方法中會將這個對象賦值個Retrofit
對象。
public final class Retrofit { ... public static final class Builder { private @Nullable okhttp3.Call.Factory callFactory; ... public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; } ... public Retrofit build() { ... okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } ... } } ... } 複製代碼
咱們能夠看到當咱們沒有調用Retrofit.Builder.callFactory
方法時,會給咱們默認設置一個OkHttpClient
對象。
baseUrl
做爲請求的基礎路徑,它與咱們在HTTP API
接口中定義的方法註解中的相對路徑組成了完整的請求路徑。咱們能夠調用Retrofit.Builder.baseUrl
方法進行設置,最後經過Retrofit.Builder.build
方法中會將這個對象賦值個Retrofit
對象。
public final class Retrofit { ... public static final class Builder { private @Nullable HttpUrl baseUrl; ... // 傳入URL public Builder baseUrl(URL baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl.toString())); } // 傳入String public Builder baseUrl(String baseUrl) { checkNotNull(baseUrl, "baseUrl == null"); return baseUrl(HttpUrl.get(baseUrl)); } public Builder baseUrl(HttpUrl baseUrl) { // 判空 checkNotNull(baseUrl, "baseUrl == null"); // 將url進行分割 List<String> pathSegments = baseUrl.pathSegments(); // 若是baseUrl不是以"/"結尾,拋出異常 if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; } ... public Retrofit build() { ... // 再次判空 if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } ... // 傳入Retrofit對象中 return new Retrofit(..., baseUrl, ..., ..., ..., ...); } } ... } 複製代碼
設置的流程:
一、 能夠調用兩種方法,分別傳入
URL
和String
。
二、 對baseUrl
進行判空,而後進行分割,若是是以"/"
結尾會拋出異常。
三、 再進行一次判空,最後賦值給Retrofit
對象。
converterFactories
集合內部存放的都是Converter.Factory
對象,咱們能夠調用Retrofit.Builder.addConverterFactory
方法進行添加。
public final class Retrofit { ... public static final class Builder { private final List<Converter.Factory> converterFactories = new ArrayList<>(); ... public Builder addConverterFactory(Converter.Factory factory) { // 檢查factory是否爲null,而後加入到集合中 converterFactories.add(checkNotNull(factory, "factory == null")); return this; } ... public Retrofit build() { List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. // 首先添加BuiltInConverters converterFactories.add(new BuiltInConverters()); // 而後添加調用addConverterFactory方法傳入的Converter.Factory的集合 converterFactories.addAll(this.converterFactories); // 最後添加platform默認的Converter.Factory集合 converterFactories.addAll(platform.defaultConverterFactories()); // 根據converterFactories建立一個不可變集合傳入 return new Retrofit(..., ..., unmodifiableList(converterFactories), ..., ..., ...); } } ... } 複製代碼
Converter.Factory
從字面意思咱們能猜出它是和轉換有關,具體的探究會放到下文中。
callAdapterFactories
集合中存放的是CallAdapter.Factory
對象,調用Retrofit.Builder.addCallAdapterFactory
方法來設置。
public final class Retrofit { ... public static final class Builder { private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); ... public Builder addCallAdapterFactory(CallAdapter.Factory factory) { callAdapterFactories.add(checkNotNull(factory, "factory == null")); return this; } ... public Retrofit build() { List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); // 這裏不只添加了調用addCallAdapterFactory方法時設置的CallAdapter.Factory對象 // 同時還添加了platform中默認的CallAdapter.Factory對象 callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); // 根據callAdapterFactories建立一個不可變的集合傳入 return new Retrofit(..., ..., ..., unmodifiableList(callAdapterFactories), ..., ...); } } ... } 複製代碼
CallAdapter.Factory
從字面意思能夠看出是請求適配器,有關於請求適配器是什麼,也會放到下文中進行探究。
設置回調執行器咱們能夠經過Retrofit.Builder.callbackExecutor
來設置,默認的會使用Platform
的回調執行器,也就是會將請求的執行結果回調到Android
主線程中。
public final class Retrofit { ... public static final class Builder { private @Nullable Executor callbackExecutor; ... public Builder callbackExecutor(Executor executor) { this.callbackExecutor = checkNotNull(executor, "executor == null"); return this; } ... public Retrofit build() { Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { // 默認爲platform中的回調執行器,會將請求結果回調到Android主線程 callbackExecutor = platform.defaultCallbackExecutor(); } return new Retrofit(..., ..., ..., ..., callbackExecutor, ...); } } ... } 複製代碼
這個標識表示是否須要提早驗證HTTP API
接口中的方法,咱們經過調用Retrofit.Builder.validateEagerly
方法進行設置,默認爲false
。
public final class Retrofit { ... public static final class Builder { private boolean validateEagerly; ... public Builder validateEagerly(boolean validateEagerly) { this.validateEagerly = validateEagerly; return this; } ... public Retrofit build() { ... return new Retrofit(..., ..., ..., ..., ..., validateEagerly); } } ... } 複製代碼
到這裏咱們已經把Retrofit.Buidler
中的屬性分析完了,可是咱們還遺留了兩個問題:CallAdapter.Factory
和Converter.Factory
。這兩個類究竟是作什麼的?這裏來看一下。
既然咱們已經知道這個類是用來進行請求適配的,那麼咱們看一下里面是怎麼運行的。
// 將響應類型爲R的Call調整爲T類型 public interface CallAdapter<R, T> { // 返回此適配器將HTTP響應正文轉換爲Java時使用的值類型對象。 // 例如, Call <Repo>的響應類型是Repo。 這個類型用於準備傳遞給adapt的call。 Type responseType(); // 這個方法是將Call<R>對象轉成代理類T T adapt(Call<R> call); //CallAdapter工廠,retrofit默認的DefaultCallAdapterFactory其中不對Call作處理,是直接返回Call。 abstract class Factory { // 在這個方法中判斷returnType是不是咱們支持的類型, // DefaultCallAdapterFactory沒有作處理,由於在定義HTTP API接口中的方式時,returnType 即爲Call<Requestbody> // RxJavaCallAdapterFactory 就是判斷returnType是否是Observable<?> 類型 // 不支持時返回null // 返回值必須是Custom而且帶有泛型(參數類型),根據HTTP API接口中的方法返回值,肯定returnType // 如: CustomCall<String> getCategories(),那肯定returnType就是CustomCall<String> public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); // 用於獲取泛型的參數 如 Call<Requestbody> 中 Requestbody protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } // 用於獲取泛型的原始類型 // 如Call<Requestbody>拿到的原始類型就是Call protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } } } 複製代碼
看了這麼多代碼,可能仍是有點雲裏霧裏,咱們找兩個例子看一下。
final class DefaultCallAdapterFactory extends CallAdapter.Factory { @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { // 若是返回值不是Call類型返回空 // 也就是說咱們在定義HTTP API接口中的方法時,返回值不是Call<?>類型的,將不會處理 if (getRawType(returnType) != Call.class) { return null; } return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return ...; } @Override public Call<Object> adapt(Call<Object> call) { return ...; } }; } ... } 複製代碼
咱們常常會看到Retrofit + RxJava
進行網絡封裝,若是要將Retrofit
和RxJava
結合到一塊兒就須要RxJavaCallAdapterFactory
。
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory { ... @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { Class<?> rawType = getRawType(returnType); boolean isSingle = rawType == Single.class; boolean isCompletable = rawType == Completable.class; // 若是返回值不是Observable類型返回空 // 也就是說咱們在定義HTTP API接口中的方法時,返回值不是Observable<?>類型的,將不會處理 if (rawType != Observable.class && !isSingle && !isCompletable) { return null; } ... } } 複製代碼
通過上面兩個例子咱們應該對CallAdapter.Factory
有所瞭解了,這裏來解釋一下吧。
在咱們定義
HTTP API
接口時,裏面方法的返回值須要由Retrofit
中添加的CallAdapter.Factory
決定,若是定義了CallAdapter.Factory
不支持的類型,請求將不會被執行。
從上面咱們也知道Converter.Factory
適用於轉換的,咱們看下源碼,看看它究竟是怎麼轉換的。
// 將F類型轉成T類型 public interface Converter<F, T> { @Nullable T convert(F value) throws IOException; abstract class Factory { // 判斷可否將API方法的返回類型從ResponseBody 轉換爲type // 若是不能直接返回null,反之返回對應的Converter.Factory對象 // type是由CallAdapter 接口裏面的responseType()函數返回的。 public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } // 將API方法的輸入參數類型從 type轉換爲requestBody // 用於轉換被註解@Body, @Part 和 @PartMap標記的類型 public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; } // 將API方法的輸入參數類型從 type 轉換爲String // 用於轉換被註解 @Header, @HeaderMap, @Path, @Query 和 @QueryMap 標記的類型 public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } // 從type中提取index處泛型參數的上界 // 例如Map<String, ? extends Runnable>索引爲1處返回Runnable protected static Type getParameterUpperBound(int index, ParameterizedType type) { return Utils.getParameterUpperBound(index, type); } // 從type中提取原始類類型 // 例如:List<? extends Runnable>返回的是List.class protected static Class<?> getRawType(Type type) { return Utils.getRawType(type); } } } 複製代碼
看完以後仍是有點懵懵噠,咱們仍是找一個列子,還記的咱們調用Retrofit.Builder.addConverterFactory
傳入的GsonConverterFactory
嗎,看一下。
// 這個Converter.Factory類使用Gson來解析Json public final class GsonConverterFactory extends Converter.Factory { // 使用默認的Gson對象來建立GsonConverterFactory // 經過Gson將對象序列化或者反序列化成Json字符串 public static GsonConverterFactory create() { return create(new Gson()); } public static GsonConverterFactory create(Gson gson) { // 檢查傳入的gson對象是否爲空 // 若是爲空直接拋出異常 if (gson == null) throw new NullPointerException("gson == null"); return new GsonConverterFactory(gson); } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonRequestBodyConverter<>(gson, adapter); } } // 將API方法的返回類型從ResponseBody 轉換爲type 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(); } } } // 將API方法的輸入參數類型從 type轉換爲requestBody final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8"); private static final Charset UTF_8 = Charset.forName("UTF-8"); private final Gson gson; private final TypeAdapter<T> adapter; GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public RequestBody convert(T value) throws IOException { Buffer buffer = new Buffer(); Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); JsonWriter jsonWriter = gson.newJsonWriter(writer); adapter.write(jsonWriter, value); jsonWriter.close(); return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); } } 複製代碼
從GsonRequestBodyConverter
的例子中咱們總結一下Converter.Factory
的做用:
Converter.Factory
是將HTTP API
方法中的參數在requestBody和responseBody
之間進行轉換。
到這裏咱們纔算真正的把Retrofit.Buidler
中所涉及的屬性和類分析完,休息一下,進行下半部分的分析。
public final class Retrofit { ... public <T> T create(final Class<T> service) { // 一、驗證HTTP API接口 Utils.validateServiceInterface(service); if (validateEagerly) { // 二、驗證HTTP API接口中的方法 eagerlyValidateMethods(service); } // 三、動態代理,整個Retrofit的核心之一 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; @Override public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); } ... } 複製代碼
上面這段代碼中有給出了三處註釋,咱們逐個看一下
從註釋1
中咱們得知這個方法是對咱們定義的HTTP API
接口進行驗證,看一下它是怎麼驗證的。
final class Utils { ... static <T> void validateServiceInterface(Class<T> service) { if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); } if (service.getInterfaces().length > 0) { throw new IllegalArgumentException("API interfaces must not extend other interfaces."); } } ... } 複製代碼
這裏作了兩步驗證:
一、驗證傳入的對象是不是一個接口,若是不是直接拋出異常。
二、若是是一個接口,看看這個接口是不是繼接口,若是繼承了,也會拋出異常。
if (validateEagerly) { eagerlyValidateMethods(service); } 複製代碼
這裏是註釋2
處的代碼,validateEagerly
這個變量在以前的代碼註釋中已經給出瞭解釋,它是對方法進行提早驗證的標識,通常爲false
,可是咱們仍是須要看一下這個方法中是怎麼進行驗證的。
private void eagerlyValidateMethods(Class<?> service) { Platform platform = Platform.get(); //得到接口中全部定義的方法,並遍歷 for (Method method : service.getDeclaredMethods()) { // 一、判斷是否若是是default方法,Android平臺返回false // 二、判斷方法是不是靜態方法 if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) { // 若是符合條件,直接加載 loadServiceMethod(method); } } } 複製代碼
在eagerlyValidateMethods
方法中也是作了兩件事:
一、找出接口中的全部方法,看看是否符合條件。
二、若是符合條件,直接加載方法。
public final class Retrofit { //緩存集合,支持多線程訪問、線程安全 //key:Method //value:Method對應的ServiceMethod private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>(); ... ServiceMethod<?> loadServiceMethod(Method method) { // 一、首先從方法緩存集合中獲取 ServiceMethod<?> result = serviceMethodCache.get(method); // 二、若是有,直接返回 if (result != null) return result; synchronized (serviceMethodCache) { // 三、在再次確認緩存中的是否有方法 result = serviceMethodCache.get(method); if (result == null) { // 四、對方法的註解進行解析 result = ServiceMethod.parseAnnotations(this, method); // 五、將方法傳到方法緩存集合中 serviceMethodCache.put(method, result); } } return result; } } 複製代碼
loadServiceMethod
這裏作了三步事情:
一、根據傳入的
Method
從緩存集合中獲取對應的ServiceMethod
對象,若是有,直接返回;若是沒有,對集合進行加鎖,再次獲取。這種方法將對象緩存起來的作法在分析EventBus
源碼的時候就見過,目的就是爲了提升效率。
二、若是上一步中沒有獲取到ServiceMethod
對象,將對Method
進行解析。
三、將Method
和它對應的ServiceMethod
對象存入到緩存集合中,返回結果。
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke(Object[] args); } 複製代碼
註釋2
處的驗證HTTP API
接口中的方法咱們先分析到這裏,上面這段代碼咱們先不進行探究,由於很快咱們又會看到,具體流程會在接下來的分析中詳細探究,但願你們對這個方法有所印象。咱們先來總結一下註釋2
處都是作了哪些事情:
一、獲取到
HTTP API
接口中全部方法,遍歷加載這些方法。
二、加載的過程當中先去緩存集合中看一下有沒有與Method
對應的ServiceMethod
對象,若是有,直接返回;若是沒有,對Method
進行解析,將解析結果封裝成一個ServiceMethod
對象,並存入到緩存集合中,最後將ServiceMethod
返回。
public final class Retrofit { ... public <T> T create(final Class<T> service) { return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { // 一、這裏返回的是Android平臺 private final Platform platform = Platform.get(); // 二、建立一個Object數組,長度爲0 private final Object[] emptyArgs = new Object[0]; @Override public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // 三、若是該方法是來自Object的方法,則聽從正常調用。 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } // 四、在Android平臺始終返回false if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } // 五、加載方法 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); } ... } 複製代碼
當調用retrofit.create(ServiceApi.class)
實際上會生成一個ServiceApi
的代理類對象。從前面的基礎知識準備中咱們知道,當調用代理類對象中的方法時,最終會調用建立代理類對象所傳入的第三個參數InvocationHandler.invoke
方法回調中去,在這個回調中對方法進行處理。retrofit.create(ServiceApi.class)
方法的主要流程已經在上面的代碼註釋中給出,這個方法最重要的一步是最後的加載方法,咱們來看一下。
ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; } 複製代碼
嗯哼?上面這段代碼是否是很是熟悉?沒錯,在之提早驗證方法的過程當中,咱們已經見到過這個方法,方法中的流程這裏就再也不贅述,咱們繼續往下看。
abstract class ServiceMethod<T> { static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { // 一、根據傳入的retrofit和method對象封裝成RequestFactory // 這一步主要是進行解析註解 RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); // 二、獲取方法的returnType Type returnType = method.getGenericReturnType(); // 三、對方法的returnType進行驗證 if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } // 四、對方法的註解進行解析,並封裝成一個ServiceMethod對象 // 這裏返回的是HttpServiceMethod對象,他是ServiceMethod的子類 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke(Object[] args); } 複製代碼
哎呦,這個方法咱們也見過,當時只是加深了一下印象,並無對其進行探究。這個方法中作了四步操做,它們對應的操做已經在上面代碼的註釋中給出。咱們重點來看一下第一步和第四步。
這個方法主要是根據傳入的retrofit
對象和method
對象封裝成RequestFactory
對象。
final class RequestFactory { static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } // method對象 private final Method method; // 基礎url private final HttpUrl baseUrl; // 請求方法 final String httpMethod; // 相對url,它與基礎url組成請求路徑 private final @Nullable String relativeUrl; // 請求頭 private final @Nullable Headers headers; // 表示具體請求中的媒體類型信息 private final @Nullable MediaType contentType; // 是否有請求體 private final boolean hasBody; // 是不是Form表單提交 private final boolean isFormEncoded; // 是否支持文件上傳的Form表單 private final boolean isMultipart; // private final ParameterHandler<?>[] parameterHandlers; // 是不是kotlin掛起函數 final boolean isKotlinSuspendFunction; /** * Inspects the annotations on an interface method to construct a reusable service method. This * requires potentially-expensive reflection so it is best to build each service method only once * and reuse it. Builders cannot be reused. */ // 檢查接口方法上的註釋以構造可重用的服務方法。這須要潛在的昂貴反射,所以最好只構建一次每一個服務方法並重用它。 // 構建器不能重用。 static final class Builder { private static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*"; private static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}"); private static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM); // 傳入的retrofit對象 final Retrofit retrofit; // 傳入的method對象 final Method method; // method對象中的註解 final Annotation[] methodAnnotations; // method中參數註解數組 final Annotation[][] parameterAnnotationsArray; // method中參數類型數組 final Type[] parameterTypes; boolean gotField; boolean gotPart; boolean gotBody; boolean gotPath; boolean gotQuery; boolean gotQueryName; boolean gotQueryMap; boolean gotUrl; @Nullable String httpMethod; boolean hasBody; boolean isFormEncoded; boolean isMultipart; @Nullable String relativeUrl; @Nullable Headers headers; @Nullable MediaType contentType; @Nullable Set<String> relativeUrlParamNames; @Nullable ParameterHandler<?>[] parameterHandlers; boolean isKotlinSuspendFunction; Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; // 獲取方法註解 this.methodAnnotations = method.getAnnotations(); // 獲取方法參數類型 this.parameterTypes = method.getGenericParameterTypes(); // 獲取方法註解數組 this.parameterAnnotationsArray = method.getParameterAnnotations(); } RequestFactory build() { // 遍歷註解,對註解進行解析 for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } if (httpMethod == null) { throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.)."); } if (!hasBody) { if (isMultipart) { throw methodError(method, "Multipart can only be specified on HTTP methods with request body (e.g., @POST)."); } if (isFormEncoded) { throw methodError(method, "FormUrlEncoded can only be specified on HTTP methods with " + "request body (e.g., @POST)."); } } int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } if (relativeUrl == null && !gotUrl) { throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError(method, "Non-body HTTP method cannot contain @Body."); } if (isFormEncoded && !gotField) { throw methodError(method, "Form-encoded method must contain at least one @Field."); } if (isMultipart && !gotPart) { throw methodError(method, "Multipart method must contain at least one @Part."); } // 返回一個RequestFactory對象 return new RequestFactory(this); } // 對註解進行解析 private void parseMethodAnnotation(Annotation annotation) { // 判斷解析類型,根據註解的類型進行相應的解析 if (annotation instanceof DELETE) { parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false); } else if (annotation instanceof GET) { parseHttpMethodAndPath("GET", ((GET) annotation).value(), false); } else if (annotation instanceof HEAD) { parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false); } else if (annotation instanceof PATCH) { parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true); } else if (annotation instanceof POST) { parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); } else if (annotation instanceof PUT) { parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true); } else if (annotation instanceof OPTIONS) { parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false); } else if (annotation instanceof HTTP) { HTTP http = (HTTP) annotation; parseHttpMethodAndPath(http.method(), http.path(), http.hasBody()); } else if (annotation instanceof retrofit2.http.Headers) { String[] headersToParse = ((retrofit2.http.Headers) annotation).value(); if (headersToParse.length == 0) { throw methodError(method, "@Headers annotation is empty."); } headers = parseHeaders(headersToParse); } else if (annotation instanceof Multipart) { if (isFormEncoded) { throw methodError(method, "Only one encoding annotation is allowed."); } isMultipart = true; } else if (annotation instanceof FormUrlEncoded) { if (isMultipart) { throw methodError(method, "Only one encoding annotation is allowed."); } isFormEncoded = true; } } //解析Http請求方法和路徑 private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) { ... } // 解析請求頭 private Headers parseHeaders(String[] headers) { ... } ... } ... } 複製代碼
這裏沒有把RequestFactory
中全部的方法列出來,可是咱們從上面的代碼和註釋中咱們能夠知道這個類都是作了哪些操做:
一、建立一個
RequestFactory.Builder
對象,同時傳入Retrofit
對象和Method
對象。
二、建立完RequestFactory.Builder
對象以後,會對Method
對象的註解進行解析,解析的同時會對Buidler
對象進行初始化。
三、最後經過build
方法,建立一個RequestFactory
對象,並進行初始化。
在獲得RequestFactory
對象以後,會調用HttpServiceMethod.parseAnnotations
方法,將獲取的RequestFactory
傳入,咱們看一下這裏面都是作了什麼操做。
/** Adapts an invocation of an interface method into an HTTP call. */ // 將接口方法的調用調整爲HTTP請求 abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> { /** * Inspects the annotations on an interface method to construct a reusable service method that * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service * method only once and reuse it. */ // 檢查接口方法上的註釋,以構造一個可重用的服務方法,該服務方法表示HTTP。 // 這須要潛在的昂貴反射,所以最好只構建一次每一個服務方法並重用它。 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; boolean continuationWantsResponse = false; boolean continuationBodyNullable = false; // 得到全部方法上的全部註解 Annotation[] annotations = method.getAnnotations(); // 方法返回值類型 Type adapterType; // 是不是kotlin掛起函數 if (isKotlinSuspendFunction) { ... } else { // 獲取方法返回類型 adapterType = method.getGenericReturnType(); } // 一、獲取CallAdapter對象 // 根據以前的分析,這裏得到的是DefaultCallAdapterFactory CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); // 校驗返回類型是否正確 Type responseType = callAdapter.responseType(); // 返回類型不能爲okhttp3.Response類型 if (responseType == okhttp3.Response.class) { throw methodError(method, "'" + getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } // 返回類型不能是Response,必需要包含泛型才行,相似於Response<String> if (responseType == Response.class) { throw methodError(method, "Response must include generic type (e.g., Response<String>)"); } // TODO support Unit for Kotlin? if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) { throw methodError(method, "HEAD method must use Void as response type."); } // 二、得到Converter對象 // 因爲咱們設置了GsonConverterFactory,因此這裏得到的是GsonConverterFactory對象 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); // 獲取一個okhttp3.Call.Factory對象,其實就是一個OkHttpClient對象 okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { ... } else { ... } } private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { try { // 四、從retrofit中根據returnType和annotations獲取CallAdapter return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create call adapter for %s", returnType); } } private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter( Retrofit retrofit, Method method, Type responseType) { Annotation[] annotations = method.getAnnotations(); try { // 五、從retrofit中根據responseType和annotations獲取Converter return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(method, e, "Unable to create converter for %s", responseType); } } } public final class Retrofit { ... // 建立CallAdapter對象 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { // 調用nextCallAdapter傳入skipPast、returnType、annotations // 注意:這裏傳入的skipPast爲null return nextCallAdapter(null, returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { // 檢查一下returnType和annotations是否爲null checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); // 這裏找到callAdapterFactories集合的起始位置 // 因爲skipPast爲null因此得到的index爲-1,而後加上1,起始位置仍是0 // 開始遍歷集合 int start = callAdapterFactories.indexOf(skipPast) + 1; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { // 咱們在分析CallAdapter.Factory時知道,調用get方法表示了, // 判斷returnType是不是該CallAdapter.Factory支持的類型 // 若是不支持將會返回null // 反之會返回對應的CallAdapter.Factory // 因爲沒有額外設置,因此這裏返回的是DefaultCallAdapterFactory CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); // 若是有直接返回 if (adapter != null) { return adapter; } } // 到這裏說明沒有對應的CallAdapter.Factory // 拼接錯誤信息 StringBuilder builder = new StringBuilder("Could not locate call adapter for ") .append(returnType) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName()); } // 拋出異常 throw new IllegalArgumentException(builder.toString()); } ... // 建立Converter對象 public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) { // 調用nextResponseBodyConverter傳入skipPast、returnType、annotations // 注意:這裏傳入的skipPast爲null return nextResponseBodyConverter(null, type, annotations); } public <T> Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { // 檢查一下returnType和annotations是否爲null checkNotNull(type, "type == null"); checkNotNull(annotations, "annotations == null"); // 這裏找到converterFactories集合的起始位置 // 因爲skipPast爲null因此得到的index爲-1,而後加上1,起始位置仍是0 // 開始遍歷集合 int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { // 咱們在分析Converter.Factory時知道,調用responseBodyConverter方法表示了, // 判斷可否將API方法的返回類型從ResponseBody 轉換爲type // 若是不能直接返回null, // 返回對應的Converter.Factory對象,咱們以前設置的是GsonConverterFactory,因此這裏返回的是GsonConverterFactory Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { // 若是有直接返回 return (Converter<ResponseBody, T>) converter; } } // 到這裏說明沒有對應的Converter.Factory // 拼接錯誤信息 StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ") .append(type) .append(".\n"); if (skipPast != null) { builder.append(" Skipped:"); for (int i = 0; i < start; i++) { builder.append("\n * ").append(converterFactories.get(i).getClass().getName()); } builder.append('\n'); } builder.append(" Tried:"); for (int i = start, count = converterFactories.size(); i < count; i++) { builder.append("\n * ").append(converterFactories.get(i).getClass().getName()); } // 拋出異常 throw new IllegalArgumentException(builder.toString()); } ... } 複製代碼
這裏因爲代碼過長,因此咱們分步分析,在上面代碼中有5處
比較重要的註釋,首先看一下註釋1
和註釋2
,它們分別是用來獲取CallAdapter.Factory
和Converter.Factory
,分別對應了註釋4
和註釋5
處。註釋4
和註釋5
都是從retrofit
對象中獲取,具體的操做須要看上段代碼的下半部分,最終獲取的是DefaultCallAdapterFactory
和GsonConverterFactory
,具體流程已經在註釋中給出。
咱們來看一下註釋3
處的操做,下面是註釋3
處的代碼
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> { static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; ... // 獲取一個okhttp3.Call.Factory對象,其實就是一個OkHttpClient對象 okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { // 新建一個CallAdapted對象,傳入requestFactory、callFactory、responseConverter、callAdapter // 最後返回出去 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { ... } else { ... } } ... HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter) { this.requestFactory = requestFactory; this.callFactory = callFactory; this.responseConverter = responseConverter; } @Override final @Nullable ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); // 這裏首先找的是子類的adapt方法 // 由於建立的是CallAdapted,因此會調用CallAdapted的adapt放方法 return adapt(call, args); } protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args); // CallAdapted繼承自HttpServiceMethod static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> { private final CallAdapter<ResponseT, ReturnT> callAdapter; // CallAdapted構造方法 CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, ReturnT> callAdapter) { // 調用父類的構造方法,也就是HttpServiceMethod的構造方法 super(requestFactory, callFactory, responseConverter); this.callAdapter = callAdapter; } @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) { // 返回callAdapter.adapt的結果 return callAdapter.adapt(call); } } ... } 複製代碼
這裏咱們須要把註釋3
處的過程捋一捋,因爲這個過程跟以前的分析聯繫比較緊密,因此會有點繞:
一、新建一個
CallAdapted
對象,傳入requestFactory
、callFactory
、responseConverter
、callAdapter
。
二、建立CallAdapted
對象時調用其構造方法,因爲它繼承自HttpServiceMethod
,又調用了HttpServiceMethod
的構造方法,將參數傳入。
三、咱們在以前的動態代理最後一步會調用return loadServiceMethod(method).invoke(...)
方法以後,又回調用HttpServiceMethod.adapt
方法。這個方法在HttpServiceMethod
中屬於抽象方法,因此最終會調用其子類CallAdapted.adapt
方法。
四、在CallAdapted.adapt
的方法中會調用callAdapter.adapt
方法,在分析CallAdapte.Factory
時,咱們知道這個方法是將Call<R>
對象轉成代理類T
。咱們沒有設置CallAdapte.Factory
,因此使用的是DefaultCallAdapterFactory
,因此又調用了DefaultCallAdapterFactory
中的adapt
方法,並將OkHttpCall
傳入了。
final class DefaultCallAdapterFactory extends CallAdapter.Factory { private final @Nullable Executor callbackExecutor; // 這個構造方法在Platform的Android子類中的defaultCallAdapterFactories方法中已經被調用。 DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) { //callbackExecutor爲MainThreadExecutor,也就是說會將響應回調到Android主線程去 this.callbackExecutor = callbackExecutor; } // @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { // 若是不是Call類型不予處理 if (getRawType(returnType) != Call.class) { return null; } if (!(returnType instanceof ParameterizedType)) { throw new IllegalArgumentException( "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>"); } final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType); // 查看註解是否包含SkipCallbackExecutor類型,咱們在使用時並無使用SkipCallbackExecutor的註解 // 因此這裏的executor不爲null final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor; return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { // 判斷executor是否爲空,若是爲空返回Call,這個call屬於OkHttpCall // 若是不爲空返回ExecutorCallbackCall return executor == null ? call : new ExecutorCallbackCall<>(executor, call); } }; } ... } 複製代碼
static final class ExecutorCallbackCall<T> implements Call<T> { ... } 複製代碼
因爲這裏與以前的分析聯繫比較緊密,有些繞,一不當心就會被繞進去,因此仍是分步分析。
一、在
Platform
的子類Android
中,已經建立了DefaultCallAdapterFactory
對象,而且傳入了MainThreadExecutor
,這保證了響應會被回調到Android
主線程。
二、以前在獲取CallAdapter
類型的時候,已經調用了DefaultCallAdapterFactory.get
方法,因此executor
對象不爲空,而且返回了一個匿名的CallAdapter
對象。
三、在上面咱們調用DefaultCallAdapterFactory.adapt
方法時,就是調用了這個匿名對象的adapt
方法,這裏返回的是ExecutorCallbackCall
對象。也就是說咱們在作網絡請求時就是使用這個ExecutorCallbackCall
對象。
咱們在上面的分析中知道,實際上是ExecutorCallbackCall
對象進行網絡請求,因此看一下它的源碼。
同步請求的方法咱們也在以前的舉例給出,咱們看一下源碼
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; // 構造方法傳入callbackExecutor、Call ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { // callbackExecutor屬於MainThreadExecutor this.callbackExecutor = callbackExecutor; // delegate爲OkHttpCall對象 this.delegate = delegate; } ... @Override public Response<T> execute() throws IOException { // delegate其實就是OkHttpCall對象 return delegate.execute(); } ... } 複製代碼
final class OkHttpCall<T> implements Call<T> { @Override public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { ... call = rawCall; if (call == null) { try { // requestFactory根據args建立request對象 // 而後建立okhttp3.Call對象 call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } // 使用okhttp3.Call對象進行請求,並將響應結果進行解析 return parseResponse(call.execute()); } private okhttp3.Call createRawCall() throws IOException { // requestFactory根據args建立request對象 // 而後根據request對象建立一個okhttp3.Call對象 okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } // 返回okhttp3.Call對象 return call; } // 對響應進行解析 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); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { // 將響應體傳入responseConverter對象也就是咱們以前設置的GsonConverterFactory中去 // 將響應體轉成對應的Java對象 T body = responseConverter.convert(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; } } } 複製代碼
同步請求的過程:
一、
ExecutorCallbackCall
經過調用excute
方法,調用了傳入的OkhttpCall
對象的excute
方法。
二、OkhttpCall
的excute
方法中,首先經過requestFactory
根據args
建立request
對象,而後建立okhttp3.Call
對象。
三、調用okhttp3.Call
的excute
方法,獲取響應。
四、拿到響應後會根據響應碼進行判斷,經過判斷後經過responseConverter
對象將響應體轉成對應的Java
對象,並返回。
關於異步請求的使用,在咱們以前的舉例中已經給出。
static final class ExecutorCallbackCall<T> implements Call<T> { // callbackExecutor屬於MainThreadExecutor final Executor callbackExecutor; final Call<T> delegate; // 異步請求 @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); // 根據同步請求咱們知道delegate就是一個OkhttpCall對象 // 調用OkhttpCall.exqueue方法執行異步請求 delegate.enqueue(new Callback<T>() { // 獲取響應的回調 @Override public void onResponse(Call<T> call, final Response<T> response) { // 進行線程切換 // callbackExecutor就是MainThreadExecutor,其內部是經過主線程的Handler將Runnable發送到主線程去 // 從而達到切換線程的效果 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); } }); } }); } } 複製代碼
final class OkHttpCall<T> implements Call<T> { // 異步請求方法 @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); okhttp3.Call call; Throwable failure; synchronized (this) { ... call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { // 建立Call對象 call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } // 執行異步請求 call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { // 解析網絡請求,過程和同步請求中同樣 response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { // 請求成功的回調 callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } @Override public void onFailure(okhttp3.Call call, IOException e) { // 請求失敗 callFailure(e); } private void callFailure(Throwable e) { try { // 請求失敗回調 callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } } }); } private okhttp3.Call createRawCall() throws IOException { // requestFactory根據args建立一個request對象 // 將request對象分裝成一個Call對象 okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } } 複製代碼
異步請求中有一個重要的操做就是將請求結果經過主線程的Handle
發送到主線程去,從而達到線程切換的效果。
在源碼分析的過程當中,咱們能發現Retrofit
中運用了大量的設置模式,這樣作的好處就是將代碼進行封裝,方便咱們調用。這裏面用到的設計模式包括:構建者模式
、單例模式
、工廠模式
、代理模式
、外觀模式
、裝飾模式
、策略模式
、適配器模式
。
因爲在以前的文章中已經提到了構建者模式
、單例模式
、工廠模式
,因此這裏再也不多作陳述,可是我會給出它們在Retrofit
中具體的出處。
一、構建者模式:最明顯的就是在最初建立
Retrofit
對象時調用的new Retrofit.Builder().build()
。
二、單例模式:在Platform
類中獲取Plathform
對象時使用的就是單例模式,有關單例的幾種寫法和它們之間的區別還但願你們可以有所瞭解。
三、工廠模式:最明顯的是CallAdapter.Factory
和Converter.Factory
,可是工廠模式中又有:簡單工廠
、抽象工廠
和工廠方法
,須要區分開來。
說到代理模式,有靜態代理和動態代理之分。在Retrofit
中咱們最初接觸的是動態代理。
public final class Retrofit { ... public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); ... return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { ... @Override public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { ... } }); } ... } 複製代碼
這裏只有動態代理,那Retrofit
中的靜態代理在哪?在說靜態代理以前要明白什麼是靜態代理:靜態代理是指代理類在程序運行前已經存在的代理方式。
static final class ExecutorCallbackCall<T> implements Call<T> { ... // 這個delegate屬於靜態代理 final Call<T> delegate; @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { @Override public void run() { // 額外操做 if (delegate.isCanceled()) { ... } else { ... } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { ... } }); } } 複製代碼
有關代理模式,在基礎知識準備的時候已經給你們準備了幾篇文章,這裏就再也不一一列出了。
public interface ServiceApi { @GET("wxarticle/chapters/json") Call<Bean> getWxArtical(); } ServiceApi serviceApi = retrofit.create(ServiceApi.class); final Call<Bean> officialAccounts = serviceApi.getOfficialAccounts(); 複製代碼
咱們在HTTP API
接口中定義了不少方法,參數都在方法上進行定義,只會告訴調用者須要傳入哪些參數,具體的操做並不向外暴露,這個就是外觀設計模式。這裏爲到家準備了一篇設計模式以外觀模式。
容許向一個現有的對象添加新的功能,同時又不改變其結構。它是做爲現有的類的一個包裝。
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { ... } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback<T>() { ... }); } } 複製代碼
咱們能夠將ExecutorCallbackCall
看做是裝飾類,但真正去執行請求的是OkHttpCall。之因此要有個裝飾類,是但願作一些額外操做。這裏的操做就是線程轉換,將子線程切換到主線程上去。有關裝飾設計模式,爲你們準備了兩篇文章: 設計模式之死磕裝飾器模式(原創)、 裝飾者模式。
簡單的來講,策略模式就是作某些事情可能同時有多個方案,不一樣的時期使用不一樣的方案,怎樣在調用的過程當中儘量的減小代碼的修改,主要仍是使用了Java
中的多態。
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory { @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); Class<?> rawObservableType = getRawType(observableType); if (rawObservableType == Response.class) { ... } else if (rawObservableType == Result.class) { ... } else { ... } } ... } 複製代碼
在RxJava2CallAdapterFactory
的get
方法中使用了策略模式,這裏會根據rawObservableType
的類型,做出對應的操做,若是感興趣的小夥伴能夠到源碼裏面看一下。
有關策略模式這裏爲你們準備了一篇文章:LOL設計模式之「策略模式」。
咱們在看Retrofit
源碼時,有可能在分析CallAdapter
時被搞的暈頭轉向。若是從適配器的概念上來說,就是將一個已經存在的東西,轉成適合使用的東西。最多見的場景就是出國遊玩的時候因爲電源接口標準的不一樣,咱們須要帶一個轉換頭。
回頭看Retrofit
,若是咱們一直時在Android
上使用,那就須要經過靜態代理ExecutorCallbackCall
來切換線程,可是後來出現了新的技術Rxjava
,感受還挺好用的,不須要經過Handler
進行線程切換了。這時就須要轉換一下,將將OkHttpCall
轉換成rxjava(Scheduler)
的寫法,大概就是這麼一個套路。
關於適配器模式,也給你們準備了一篇文章:《JAVA與模式》之適配器模式
到這裏咱們已經把Retrofit
的源碼分析了一遍, 這裏仍是建議你們本身跟着源碼走一遍,畢竟紙上得來終覺淺。最後仍是那句話,本人是一名Android
小學生,文中若有不妥之處還望各位不吝賜教,本人將不勝感激。
這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)
Java註解深刻淺出
你真的徹底瞭解Java動態代理嗎?看這篇就夠了
Java動態代理
10分鐘看懂動態代理設計模式
設計模式之死磕裝飾器模式(原創)
LOL設計模式之「策略模式」
裝飾者模式
《JAVA與模式》之適配器模式
wanandroid開放API