自從Android誕生以來,Bitmap的管理就一直是大問題,爲了更好的管理它,不一樣的圖片加載框架不斷的被推出,從剛開始的ImageLoader,到Picasso,再到如今的Fresco和Glide,可謂百花齊放。然而前二者如今都已經再也不維護了,同時咱們公司的項目目前也已經從Fresco切換到Glide了,以前之因此用Fresco是由於他在Android5.0如下系統中能從native層「偷」內存,但後面因爲Android對於Bitmap內存管理方式的改變,這個功能再也不生效,相比於Glide來講,Fresco就顯得侵入性太強,並且可擴展性沒有glide強。而Glide之因此擴展性如此強,就在於它 優秀的架構設計 ,這也是咱們今天要討論的。面試
首先咱們看下Glide整體架構圖:編程
從架構圖上,咱們能夠看出,glide並無着眼於bitmap,而是進行了高度的抽象,因此咱們不該該將glide當作一個圖片加載框架,而是一個資源從不一樣形態之間轉換的框架,從url到bitmap只是其中一種,因此咱們不難理解glide甚至能從視頻加載第一幀,由於它沒有對輸入類型作任何限制,都是統一抽象成的Request。設計模式
這裏以從url到inputstream二進制流爲例,之因此這裏有三條分路,這和glide的緩存策略有關。首先有一點要澄清,這裏從Request到Data實際上是跳過了內存緩存的介紹,畢竟若是內存中已有bitmap緩存,咱們直接取用就能夠了,無需這麼麻煩(詳細的緩存方案後續文章會介紹)。所以,這裏有三條路徑主要是磁盤緩存和網絡緩存,而磁盤緩存有兩種:數組
因爲glide的這種高度抽象,如今咱們面臨着一個問題:如此多類型的Request和如此多的Data,具體怎麼去加載它呢?好比說Request有url、uri、File、資源id、視頻等等,不一樣的Request確定有不一樣的加載方式,同一個Request既可能從網絡加載,也可能從磁盤加載,可能性太多,那麼咱們怎麼去加載呢?if-else去判斷嗎?一個優秀的框架確定不會幹這種low到爆的事。這裏咱們介紹一些新的角色:緩存
這裏,針對每一種Request,咱們都有對應的ModelLoader,當一個Request進來時,咱們能夠遍歷全部的ModelLoader,經過handles()方法判斷這個ModelLoader可否處理這種Request,這樣咱們就能解決第一個問題,即不一樣的Request如何管理加載,有了ModelLoader機制,若是咱們想增長一種Request,咱們只要開發對應的ModelLoader便可。網絡
有了ModelLoader,實際上是不夠的,它只是用來判斷這個Request是否可否處理,爲了能真正的加載請求,Glide引入了DataFetcher,不一樣的方式對應一個不一樣的DataFetcher,二者職責分離,這是由於同一種Request其實有不少加載方式,好比從網絡加載,從磁盤加載等等,很是複雜,因此這裏獨立出一個DataFetcher。其中LoadData只是對DataFetcher的一種包裝,多包含了一些信息而已。架構
如今,咱們根據傳入的請求具體類型(好比url仍是file仍是字節數組),經過遍歷全部的ModelLoader判斷該ModelLoader可否處理這種請求,而後用該ModelLoader中的DataFetcher去具體加載這個請求。框架
有了ModelLoader和DataFetcher機制,Glide已經能方便的將一個原始請求從不一樣的地方加載到內存中了,這個時候這份數據還只是單純的二進制數據(攜帶了格式數據)而已,咱們稱其爲Data,如今須要進行解碼過程,剔除原始的格式信息,而後拿原始信息從新編碼,將其轉化成不一樣的格式,好比將一個jpg先解碼而後轉碼成Bitmap,或者轉碼成Gif,解碼以及轉碼後的數據咱們稱其爲Resource。如今面臨的問題仍是同樣的:ide
因爲框架的設計決定了須要解碼的格式是不定的,要轉碼的格式也是不定的,如何高效的組織這個過程呢?學習
這個和Request被加載的過程相似,這裏採用的是模板方法設計模式:
能夠看到,這裏咱們能從Registry中獲取全部的ResourceDecoder和ResourceTranscoder,而後判斷哪一個解碼器或轉碼器適合當前格式,直接調用相關的decode和transcode方法就能夠了。
以這種方式,咱們能隨意擴展不一樣格式的解碼和轉碼了。
資源解碼並轉碼後,因爲某些特殊的需求,咱們是不能直接使用的,好比有圓角需求,透明度需求等等,完成這步轉換的,就是Transformation。因爲這一步轉換是可選的,和上面兩步都不一樣必須進過的步驟不一樣,這裏的Transformation就不能存在一個地方主動去取,必須是得構建這整個流程的時候指定使用哪一個Transformation,這裏沒有什麼複雜的架構,你們瞭解下Transformation的大體狀況便可:
如今咱們走到了最後一步,須要將符合條件的Resource顯示在指定的Target上,固然具體如何顯示細節本文不討論,咱們主要關注的是顯示時候的動畫操做,也就是通過Transition的 transition()。這一步和上面一步相似,是否須要使用Transition和使用哪一個Transition都是由請求時用戶決定的,所以這裏也沒有複雜架構,你們看下Transition的組成便可:
其實從整體架構上來講,Glide的設計無疑是很是完美的,每個步驟都是面對接口編程,能夠隨意新增或修改其中的某一步,擴展性很是強,這雖然讓架構變的更加複雜,但這點代價是值得的。以這個架構來講,只要Android不死,Glide都能一直用下去。
最後,本文只是簡單的給你們一個Glide的大體流程,每一個流程是怎麼回事,讓你們有個概念,甚至連最複雜的緩存都沒提到,更不用說每一步的具體流程了,針對這些,我將會繼續寫一系列的文章,但願能將Glide說清楚。