【建議收藏】面試沒有亮點?給你一份Android熱門三方庫源碼面試寶典

前言

成爲一名優秀的Android開發,須要一份完備的知識體系,在這裏,讓咱們一塊兒成長爲本身所想的那樣~。

衆所周知,優秀源碼的閱讀與理解是最能提高自身功力的途徑,若是想要成爲一名優秀的Android工程師,那麼Android中優秀三方庫源碼的分析和理解則是必備技能。就拿比較熱門的圖片加載框架Glide來講,相信不少同窗都使用過,那麼,當別人問你下面這些問題時你是否能回答出來呢?(Glide五連發)android

  • 一、爲何要在項目中使用這個庫?
  • 二、這個庫都有哪些用法?對應什麼樣的使用場景?
  • 三、這個庫的核心實現原理是什麼?若是讓你實現這個庫的某些核心功能,你會考慮怎麼去實現?
  • 四、Glide源碼機制的核心思想是什麼?
  • 五、Glide中是如何計算一張圖片的大小的?

相信能所有回答出來的同窗並很少,下面我來解答一下上面幾個問題。git

一、爲何要在項目中使用這個庫?

  • 一、多樣化媒體加載:不只能夠進行圖片緩存,還支持Gif、WebP、縮略圖,甚至是Video。
  • 二、經過設置綁定生命週期:可使加載圖片的生命週期動態管理起來。
  • 三、高效的緩存策略:支持內存、Disk緩存,而且Picasso只會緩存原始尺寸的圖片,而Glide緩存的是多種規格,也就是Glide會根據你ImageView的大小來緩存相應大小的圖片尺寸。
  • 四、內存開銷小:默認的Bitmap格式是RGB_565格式,而Picasso默認的是ARGB_8888格式,內存開銷小一半。

二、這個庫都有哪些用法?對應什麼樣的使用場景?

  • 一、圖片加載:Glide.with(this).load(imageUrl).override(800, 800).placeholder().error().animate().into()。
  • 二、多樣式媒體加載:asBitamp、asGif。
  • 三、生命週期集成。
  • 四、能夠配置磁盤緩存策略ALL、NONE、SOURCE、RESULT。

三、這個庫的核心實現原理是什麼?若是讓你實現這個庫的某些核心功能,你會考慮怎麼去實現?

要想了解Glide的核心實現原理,就必須先從它的加載API Glide.with().into()來進行分析。github

一、Glide&with:

  • 一、初始化各式各樣的配置信息(包括緩存,請求線程池,大小,圖片格式等等)以及glide對象。
  • 二、將glide請求和application/SupportFragment/Fragment的生命週期綁定在一塊。

二、Glide&load:

設置請求url,並記錄url已設置的狀態。面試

三、Glide&into:

  • 一、首先根據轉碼類transcodeClass類型返回不一樣的ImageViewTarget:BitmapImageViewTarget、DrawableImageViewTarget。
  • 二、遞歸創建縮略圖請求,沒有縮略圖請求,則直接進行正常請求。
  • 三、若是沒指定寬高,會根據ImageView的寬高計算出圖片寬高,最終執行到onSizeReay()方法中的engine.load()方法。
  • 四、engine是一個負責加載和管理緩存資源的類

其中Glide的三層緩存機制是值得咱們去反覆學習揣摩的,這裏咱們先了解下常規的三級緩存是怎樣的。數據庫

常規三級緩存的流程:強引用->軟引用->硬盤緩存

當咱們的APP中想要加載某張圖片時,先去LruCache中尋找圖片,若是LruCache中有,則直接取出來使用,若是LruCache中沒有,則去SoftReference中尋找(軟引用適合當cache,當內存吃緊的時候纔會被回收。而weakReference在每次system.gc()就會被回收)(當LruCache存儲緊張時,會把最近最少使用的數據放到SoftReference中),若是SoftReference中有,則從SoftReference中取出圖片使用,同時將圖片從新放回到LruCache中,若是SoftReference中也沒有圖片,則去硬盤緩存中中尋找,若是有則取出來使用,同時將圖片添加到LruCache中,若是沒有,則鏈接網絡從網上下載圖片。圖片下載完成後,將圖片保存到硬盤緩存中,而後放到LruCache中。編程

Glide的三層緩存機制

Glide緩存機制大體分爲三層:內存緩存、弱引用緩存、磁盤緩存。json

  • 取的順序是:內存、弱引用、磁盤。
  • 存的順序是:弱引用、內存、磁盤。

三層存儲的機制在Engine中實現的。先說下Engine是什麼?Engine這一層負責加載時作管理內存緩存的邏輯。持有MemoryCache、Map<Key, WeakReference<EngineResource<?>>>。經過load()來加載圖片,加載先後會作內存存儲的邏輯。若是內存緩存中沒有,那麼纔會使用EngineJob這一層來進行異步獲取硬盤資源或網絡資源。EngineJob相似一個異步線程或observable。Engine是一個全局惟一的,經過Glide.getEngine()來獲取。設計模式

須要一個圖片資源,若是Lrucache中有相應的資源圖片,那麼就返回,同時從Lrucache中清除,放到activeResources中。activeResources map是盛放正在使用的資源,以弱引用的形式存在。同時資源內部有被引用的記錄。若是資源沒有引用記錄了,那麼再放回Lrucache中,同時從activeResources中清除。若是Lrucache中沒有,就從activeResources中找,找到後相應資源引用加1。若是Lrucache和activeResources中沒有,那麼進行資源異步請求(網絡/diskLrucache),請求成功後,資源放到diskLrucache和activeResources中。緩存

四、Glide源碼機制的核心思想:

使用一個弱引用map activeResources來盛放項目中正在使用的資源。Lrucache中不含有正在使用的資源。資源內部有個計數器來顯示本身是否是還有被引用的狀況,把正在使用的資源和沒有被使用的資源分開有什麼好處呢??由於當Lrucache須要移除一個緩存時,會調用resource.recycle()方法。注意到該方法上面註釋寫着只有沒有任何consumer引用該資源的時候才能夠調用這個方法。那麼爲何調用resource.recycle()方法須要保證該資源沒有任何consumer引用呢?glide中resource定義的recycle()要作的事情是把這個不用的資源(假設是bitmap或drawable)放到bitmapPool中。bitmapPool是一個bitmap回收再利用的庫,在作transform的時候會從這個bitmapPool中拿一個bitmap進行再利用。這樣就避免了從新建立bitmap,減小了內存的開支。而既然bitmapPool中的bitmap會被重複利用,那麼確定要保證回收該資源的時候(即調用資源的recycle()時),要保證該資源真的沒有外界引用了。這也是爲何glide花費那麼多邏輯來保證Lrucache中的資源沒有外界引用的緣由。網絡

五、Glide中是如何計算一張圖片的大小的?

圖片佔用內存的計算公式:圖片高度 * 圖片寬度 * 一個像素佔用的內存大小。因此,計算圖片佔用內存大小的時候,要考慮圖片所在的目錄跟設備密度,這兩個因素其實影響的是圖片的寬高,android會對圖片進行拉昇跟壓縮。

上面筆者只是簡單地講解一下下Glide的內部實現機制,可是這是遠遠不夠的,若是想要對Glide或其它熱門三方庫有足夠具象地瞭解,就必須深刻源碼去感覺其中的藝術。

助力一份Android熱門三方庫源碼面試寶典

所以,爲了將熱門三方庫涉及的知識成體系地融合起來,筆者建立了Awesome-Third-Library-Source-Analysis這個項目,爲的就是讓每個Android工程師可以從如下七個方面全方位地提高本身的技術實力。

項目地址:Awesome-Third-Library-Source-Analysis

 

深刻理解熱門三方庫實現原理,從七個角度全方位提高你的功力~

Contents

網絡

Android最優秀的網絡底層框架,沒有之一。

Android最優秀的網絡封裝框架,內含九種經常使用設計模式的靈活運用。

圖片

Android使用最普遍的圖片加載框架。

數據庫

Android中數據庫操做綜合效率最高的框架。

響應式編程

來一塊兒探究RxJava的異步、簡潔、優雅和它強大的操做符吧!

內存泄露

LeakCanary到底是如何檢測出內存泄露的呢?

依賴注入

使用APT + 註解攻破了findViewByid(),JW大神之做。

Dagger就一把匕首,在中大型項目中,它能提高開發效率、自動管理類的實例、解耦,是如此的乾脆。

事件總線

使用擴展的觀察者模式實現的組件間通訊框架,廣播的替代者。

做者:jsonchao
連接:https://juejin.im/post/5e65ad276fb9a07cc01a3264來源:掘金

相關文章
相關標籤/搜索