Retrofit分析-漂亮的解耦套路


沒耐心自己分析源碼的同學,還可以參考Stay錄制的視頻版

Retrofit分析-漂亮的解耦套路(視頻版)

萬萬沒想到Retrofit會這么火,在沒看源碼之前,我簡單的認為是因為它跟OkHttp同出一源(Square),所以才會炒的那么熱。又或者是因為它能支持RxJava,所以火上澆油,一發不可收拾。

后來看過Retrofit源碼之后,我才理解為什么它倍受關注,是因為它集諸優點於一身,並且炒雞解耦。你能預見的特殊需求,都能非常容易的擴展。

沒有HTTP框架的日子

我們先來看一下沒有HTTP框架以前,我們是如何做請求的。

retrofit00.png

  1. 首先build request參數
  2. 因為不能在主線程請求HTTP,所以你得有個Executer或者線程
  3. enqueue后,通過線程去run你的請求
  4. 得到服務器數據后,callback回調給你的上層。

大概是以上4大步驟,在沒有框架的年代,想要做一次請求,是萬分痛苦的,你需要自己管理線程切換,需要自己解析讀取數據,解析數據成對象,切換回主線程,回調給上層。

這段空白的時間持續了很久。從我10年工作起到12年,因為寫煩了重復的代碼,所以就得想辦法,把那些變化的地方封裝起來,也只是簡單的封裝。好在官方出了AsyncTask,雖然坑很多,但如果再自己維護一個隊列,基本不會出現問題。更好的地方是數據格式從xml變成json了。gson解放了雙手,再也不用解析dom了。

早些時期的HTTP框架

后來慢慢出了不少真正的HTTP框架。Stay也借鑒了很多文章,封裝了一套適用於自身業務需求的框架。

這個時期的框架有個特點,就是拼了命去支持所有類型。比方說Volley支持直接返回Bitmap。xUtils不僅大而全,而且連多線程下載也要支持。在資源匱乏的時代,它們的存在有它們的道理。但如果說現在還用Volley做圖片請求,還在用xUtils或Afinal里的各個模塊。那就說不過去了。術業有專攻,百家爭鳴的時期,難道不該選擇最好的那一個嗎?(Stay沒真的用過xUtils和Afinal這種組合框架,潛意識告訴我,它們有毒,一旦某個環節出問題或者需要擴展,那代價就太大了)

Retrofit

好吧,介紹完HTTP框架的發展,讓我們單純的說說Retrofit吧。

tips:本文以retrofit最新版本2.0.1為例,大家也可以去github下源碼,找tag為’parent-2.0.1’就可以。目前代碼變動比較大。2.0.1已經使用okhttp3了,而我項目中2.0.0-beta2還是okhttp2.5。

retrofit的最大特點就是解耦,要解耦就需要大量的設計模式,假如一點設計模式都不懂的人,可能很難看懂retrofit。

先來看一張Stay畫的精簡流程圖(如有錯誤,請斧正),類圖就不畫了。
retrofit01.png

Stay在一些設計模式很明確的地方做了標記。

外觀模式,動態代理,策略模式,觀察者模式。當然還有Builder模式,工廠等這些簡單的我就沒標。

先簡述下流程吧:

  1. 通過門面Retrofit來build一個Service Interface的proxyretrofit03.png
  2. 當你調用這個Service Interface中的某個請求方法,會被proxy攔截。retrofit02.png
  3. 通過ServiceMethod來解析invoke的那個方法 ,通過解析注解,傳參,將它們封裝成我們所熟悉的request。然后通過具體的返回值類型,讓之前配置的工廠生成具體的CallAdapterResponseConverter,這倆我們稍后再解釋。
  4. new一個OkHttpCall,這個OkHttpCall算是OkHttp的包裝類,用它跟OkHttp對接,所有OkHttp需要的參數都可以看這個類。當然也還是可以擴展一個新的Call的,比如HttpUrlConnectionCall。但是有點耦合。看下圖標注:retrofit031.png紅框中顯式的指明了OkHttpCall,而不是通過工廠來生成Call。所以如果你不想改源碼,重新編譯,那你就只能使用OkHttp了。不過這不礙事。(可能也是因為還在持續更新中,所以這塊可能后面會改進的)
  5. 生成的CallAdapter有四個工廠,分別對應不同的平台,RxJava, Java8, Guava還有一個Retrofit默認的。這個CallAdapter不太好用中文解釋。簡單來說就是用來將Call轉成T的一個策略。因為這里具體請求是耗時操作,所以你需要CallAdapter去管理線程。怎么管理,繼續往下看。
  6. 比如RxJava會根據調用方法的返回值,如Response<’T> |Result<’T>|Observable<’T> ,生成不同的CallAdapter。實際上就是對RxJava的回調方式做封裝。比如將response再拆解為success和error等。(這塊還是需要在了解RxJava的基礎上去理解,以后有時間可以再詳細做分析)
  7. 在步驟5中,我們說CallAdapter還管理線程。比方說RxJava,我們知道,它最大的優點可以指定方法在什么線程下執行。如圖retrofit04.png我們在子線程訂閱(subscribeOn),在主線程觀察(observeOn)。具體它是如何做的呢。我們看下源碼retrofit05.png。在adapt Call時,subscribeOn了,所以就切換到子線程中了。
  8. 在adapt Call中,具體的調用了Call execute(),execute()是同步的,enqueue()是異步的。因為RxJava已經切換了線程,所以這里用同步方法execute()。retrofit06.png
  9. 接下來的具體請求,就是OkHttp的事情了,retrofit要做成的就是等待返回值。在步驟4中,我們說OkHttpCall是OkHttp的包裝類,所以將OkHttp的response轉換成我們要的T,也是在OkHttpCall中執行的。
  10. 當然具體的解析轉換操作也不是OkHttpCall來做的,因為它也不知道數據格式是什么樣的。所以它只是將response包裝成retrofit標准下的response。
  11. Converter->ResponseConverter,很明顯,它是數據轉換器。它將response轉換成我們具體想要的T。Retrofit提供了很多converter factory。比如Gson,Jackson,xml,protobuff等等。你需要什么,就配置什么工廠。在Service方法上聲明泛型具體類型就可以了。
  12. 最后,通過聲明的observeOn線程回調給上層。這樣上層就拿到了最終結果。至於結果再如何處理,那就是上層的事了。

再來回顧下Stay畫的流程圖:

retrofit01.png

這真是漫長的旅行,Stay也是debug一個個單步調試才梳理出來的流程。當然其中還有很多巧妙的解耦方式,我這里就不贅述了。大家可以看看源碼分析下,當真是設計模式的經典示例。

我想現在大家應該對retrofit有所了解了。當你再給別人介紹retrofit的時候,就別只說它的注解方式多新穎,多炫技了。注解式框架有很多的,像j2ee中一大把。所以注解算不得多精湛的技藝。最牛逼的還是它的解耦方式,這個套路沒有多年的實際架構經驗是設計不出來的。

retrofit源碼暫時分析到這里,如果大家想要聽下文或者希望Stay錄個視頻帶大家一步步解析,不妨關注我,要是打賞一下鼓勵我就更好啦。

retrofit07.png

擴展閱讀:

OkHttp, Retrofit, Volley應該選擇哪一個?

Retrofit分析-謎之槽點

這么多開源框架,該用哪個好?

Retrofit分析-漂亮的解耦套路(視頻版)

聲明:本文為Stay原創,未經允許請勿轉載 有心課堂(stay4it.com) 傳遞給你的不僅僅是技術~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM