本文將帶着你,從請求執行的角度,以 interface 中咱們定義的方法爲起始,解讀 retrofit 的執行流程。目的是想讓咱們對 retrofit 的執行流程有一個框架性的瞭解,同時也是爲了面試的時候,能夠跟面試官「有的聊」。java
retrofit的核心思想是將 http 請求過程抽象成了一個對象 ServiceMethod。 這個對象的構造的時候,會經過 java 反射的方式傳入一個 method 對象,而這個對象就是咱們在 interface 中定義的請求方法。經過對 method 對象 find usage ,咱們能夠發現,一共有兩處使用了這個 method 對象:面試
ServiceMethod.createCallAdapter()編程
ServiceMethod.createResponseConverter()json
能夠看到,裏面使用了 method 對象的兩個關鍵信息:註解和返回類型。而其中涉及的兩個方法則同時出如今了 ServiceMethod.build() 中。服務器
public ServiceMethod build() { callAdapter = createCallAdapter(); responseConverter = createResponseConverter(); }
至此,咱們已經找到了 retrofit 的精妙所在:網絡
annotation 的解析是一個簡單但繁瑣的工做,須要對每個註解逐個判斷。所以咱們把重點放在 callAdapter 和 responseConverter 的分析上。而我在閱讀相關代碼的過程當中,發現其中的泛型部分對咱們理解整個框架形成了很大的阻礙。所以,想理解 retrofit,必需要弄懂其各個泛型類的意義,否則看一看就本身把本身繞暈了。框架
抽象的太複雜,不如咱們舉個例子。好比,咱們想從服務器請求電臺相關的數據,那麼,咱們的請求方法定義就多是下面這樣函數
@GET("/albums") RadioCall<RadioAlbumModel> getAlbums():
其中返回類型中涉及兩個自定義的部分:RadioCall 和 RadioAlbumModel。其中,RadioAlbumModel 是咱們定義的model 類,通常用 gson 解析服務器的數據並建立實例;RadioCall extends Call,並將請求等委託給實際的 call 對象。ui
往咱們的泛型中套用一下,代理
繼續把上面四個泛型類具化:
這樣,請求的執行流程就呼之欲出了:
首先,調用端的調用代碼應該是這樣的:
RadioCall<RadioAlbumModel> radioCall = retrofitClient.getAlbums(); radioCall.execute()
其中,getAlbums() 就是咱們的 method 方法。根據這個 method 方法, 生成 ServiceMethod 對象,返回的結果是 serviceMethod.callAdapter.adapt(okHttpCall); 。而咱們知道,咱們在 interface 中定義的 getAlbums() 的返回類型剛好是 RadioCall<RadioAlbumModel>,兩個類型就這麼對上了。
在radioCall.execute() 的內部,咱們會把調用 delegates.execute() 來實際執行網絡請求。這個 delegates 的類型就是 retrofit.OkHttpCall。而後,發起請求,等待服務器返回結果,並對結果進行處理。注意,此時的結果仍是 rawResponse,即都是 json 字符串,還不是能夠直接使用的 java model 對象。這個時候,咱們就須要 responseConverter 來幫咱們進行轉換了。
在獲取到結果以後,咱們會調用 Response<T> retrofit2.OkHttpCall.parseResponse(okhttp3.Response rawResponse) 中,進而調用以下代碼
//------ in OkHttpCall.java Response<R> parseResponse(okhttp3.Response rawResponse) throws IOException { R body = serviceMethod.toResponse(cachingBody); return Response.success(body, rawResponse); } //------ in ServiceMethod.java /** Builds a method return value from an HTTP response body. */ R ServiceMethod.toResponse(ResponseBody body) throws IOException { return responseConverter.convert(body); }
正如咱們上文所說,RadioCall 通常會把一個 okHttpCall 做爲構造函數的參數,而後把實際請求委託給 okHttpCall,而後再 onResposne 回調中就能獲得上面代碼中的 Response<R>,將咱們的類帶入,就是 Response<RadioAlbumModel>。而這個,就是 execute() 的執行結果。而後咱們就能夠獲得 Response<RadioAlbumModel> 中的 model 對象了。
至此,retrofit 的請求執行流程就分析完畢。最後咱們再從宏觀的角度,從面試的角度,來闡述一下整個執行過程。
問:請簡述 retrofit 中,一個方法的執行流程。
答:
首先咱們經過咱們 create 出來的 retrofit 實例來調用接口方法。全部的 interface 方法都會在 java 動態代理機制的做用下,調用一個匿名類 new InvocationHandler 中的 invoke。在 invoke 中,會根據咱們想調用的方法 method 構造出一個 serviceMethod,而後調用 serviceMethod.callAdapter.adapt(okHttpCall) 做爲返回結果。
構造 serviceMethod 的時候,會根據 interface 中 method 的的返回類型,構造出 converter 和 callAdapter。其中, converter 通常使用 gson converter。gson converter 能夠自動將服務器返回的 json 數據轉化成 java 中的 model 類的實例。callAdapter 絕大多數的實現方式是在構造函數中接收一個 okHttpCall 實例,而後將 enqueue 和 execute 委託給這個 okHttpCall 實例來執行。okHttpCall 在獲取到服務器數據以後,會利用 serviceMethod.toResponse(body) 來對數據進行轉化。其中,轉化的時候便利用了 converter。數據轉化完成後,封裝成 Response<R> ,傳遞給調用方。其中 R 就是咱們的數據類。
關於返回類型getGenericReturnType(),會調用到下面的方法:
Type getCallResponseType(Type return) { getParameterUpperBound(0, returnType) }
這個方法的做用就是獲取實際類型。好比,若是一個方法以下:
List<String> get() { return ArrayList() }
其返回類型是List<String>,那麼,getCallResponseType(method.genericReturnType) 獲得的結果就是 String 。其中,method.returnType 爲 java.util.List,mehod.genericReturnType 爲 java.util.List<String>。