天天看點

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

前言

成為一名優秀的Android開發,需要一份完備的 知識體系 ,在這裡,讓我們一起成長為自己所想的那樣~。

衆所周知,優秀源碼的閱讀與了解是最能提升自身功力的途徑,如果想要成為一名優秀的Android工程師,那麼Android中優秀三方庫源碼的分析和了解則是必備技能。就拿比較熱門的圖檔加載架構Glide來說,相信很多同學都使用過,那麼,當别人問你下面這些問題時你是否能回答出來呢?(Glide五連發)

  • 1、為什麼要在項目中使用這個庫?
  • 2、這個庫都有哪些用法?對應什麼樣的使用場景?
  • 3、這個庫的核心實作原理是什麼?如果讓你實作這個庫的某些核心功能,你會考慮怎麼去實作?
  • 4、Glide源碼機制的核心思想是什麼?
  • 5、Glide中是如何計算一張圖檔的大小的?

相信能全部回答出來的同學并不多,下面我來解答一下上面幾個問題。

  • 1、多樣化媒體加載:不僅可以進行圖檔緩存,還支援Gif、WebP、縮略圖,甚至是Video。
  • 2、通過設定綁定生命周期:可以使加載圖檔的生命周期動态管理起來。
  • 3、高效的緩存政策:支援記憶體、Disk緩存,并且Picasso隻會緩存原始尺寸的圖檔,而Glide緩存的是多種規格,也就是Glide會根據你ImageView的大小來緩存相應大小的圖檔尺寸。
  • 4、記憶體開銷小:預設的Bitmap格式是RGB_565格式,而Picasso預設的是ARGB_8888格式,記憶體開銷小一半。

  • 1、圖檔加載:Glide.with(this).load(imageUrl).override(800, 800).placeholder().error().animate().into()。
  • 2、多樣式媒體加載:asBitamp、asGif。
  • 3、生命周期內建。
  • 4、可以配置磁盤緩存政策ALL、NONE、SOURCE、RESULT。

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

1、Glide&with:

  • 1、初始化各式各樣的配置資訊(包括緩存,請求線程池,大小,圖檔格式等等)以及glide對象。
  • 2、将glide請求和application/SupportFragment/Fragment的生命周期綁定在一塊。

2、Glide&load:

設定請求url,并記錄url已設定的狀态。

3、Glide&into:

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

其中Glide的三層緩存機制是值得我們去反複學習揣摩的,這裡我們先了解下正常的三級緩存是怎樣的。

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

當我們的APP中想要加載某張圖檔時,先去LruCache中尋找圖檔,如果LruCache中有,則直接取出來使用,如果LruCache中沒有,則去SoftReference中尋找(軟引用适合當cache,當記憶體吃緊的時候才會被回收。而weakReference在每次system.gc()就會被回收)(當LruCache存儲緊張時,會把最近最少使用的資料放到SoftReference中),如果SoftReference中有,則從SoftReference中取出圖檔使用,同時将圖檔重新放回到LruCache中,如果SoftReference中也沒有圖檔,則去硬碟緩存中中尋找,如果有則取出來使用,同時将圖檔添加到LruCache中,如果沒有,則連接配接網絡從網上下載下傳圖檔。圖檔下載下傳完成後,将圖檔儲存到硬碟緩存中,然後放到LruCache中。

Glide的三層緩存機制

Glide緩存機制大緻分為三層:記憶體緩存、弱引用緩存、磁盤緩存。

  • 取的順序是:記憶體、弱引用、磁盤。
  • 存的順序是:弱引用、記憶體、磁盤。

三層存儲的機制在Engine中實作的。先說下Engine是什麼?Engine這一層負責加載時做管理記憶體緩存的邏輯。持有MemoryCache、Map>>。通過load()來加載圖檔,加載前後會做記憶體存儲的邏輯。如果記憶體緩存中沒有,那麼才會使用EngineJob這一層來進行異步擷取硬碟資源或網絡資源。EngineJob類似一個異步線程或observable。Engine是一個全局唯一的,通過Glide.getEngine()來擷取。

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

4、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中的資源沒有外界引用的原因。

圖檔占用記憶體的計算公式:圖檔高度 圖檔寬度 一個像素占用的記憶體大小。是以,計算圖檔占用記憶體大小的時候,要考慮圖檔所在的目錄跟裝置密度,這兩個因素其實影響的是圖檔的寬高,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就一把匕首,在中大型項目中,它能提升開發效率、自動管理類的執行個體、解耦,是如此的幹脆。

事件總線

使用擴充的觀察者模式實作的元件間通信架構,廣播的替代者。

推薦閱讀:

2017-2020曆年位元組跳動Android面試真題解析(累計下載下傳1082萬次,持續更新中)

作者:jsonchao

連結:

https://juejin.im/post/5e65ad276fb9a07cc01a3264

來源:掘金