中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

原來面試的時候寫精通Glide,這樣問我這樣答

發布時間:2020-06-11 19:30:06 來源:網絡 閱讀:589 作者:Android丶VG 欄目:移動開發
前言

這幾天在很多地方看到有聊Glide的,想起前年還是去年的時候面試的時候也有問到Glide相關的,正好今天趁著周五來聊一聊面試中Glide的那些東西

  • 1 、圖片庫對比
  • 2 、LRUCache 原理
  • 3丶LruCache 底層實現原理
  • 4 、圖片加載原理
  • 5 、自己去實現圖片庫,怎么做?
  • 6 、Glide 源碼解析
  • 7 、Glide 使用什么緩存
  • 8 、Glide 內存緩存如何控制大小?
  • 9丶三級緩存原理?
  • 10丶如何設計一個大圖加載框架?
    面試整理學習路線(禁止偷偷拿走O(∩_∩)O)

    原來面試的時候寫精通Glide,這樣問我這樣答
    請查看完整的PDF版
    (更多完整項目下載。未完待續。源碼。圖文知識后續上傳github。)
    可以點擊關于我聯系我獲取完整PDF

一丶LRUCache 原理

LruCache 是個泛型類,主要原理是:把最近使用的對象用強引用存儲在 LinkedHashMap 中,當緩存滿時,把最近最少使用的對象從內存中移除,并提供 get/put 方法完成緩存的獲取和添加LruCache 是線程安全的,因為使用了 synchronized 關鍵字。

當調用 put()方法,將元素加到鏈表頭,如果鏈表中沒有該元素,大小不變,如果沒有,需調用 trimToSize 方法判斷是否超過最大緩存量,trimToSize()方法中有一個 while(true)死循環,如果緩存大小大于最大的緩存值,會不斷刪除 LinkedHashMap 中隊尾的元素,即最少訪問的,直到緩存大小小于最大緩存值。當調用 LruCache 的 get 方法時,LinkedHashMap 會調用recordAccess 方法將此元素加到鏈表頭部

二、Glide 源碼解析

1)Glide.with(context)創建了一個 RequestManager,同時實現加載圖片與組件生命周期綁定:
在 Activity 上創建一個透明的 ReuqestManagerFragment 加入到 FragmentManager 中,通過添加的 Fragment 感知Activty\Fragment 的生命周期。因為添加到 Activity 中的 Fragment 會跟隨Activity 的生命周期。在 RequestManagerFragment 中的相應生命周期方法中通過 liftcycle 傳遞給在 lifecycle 中注冊的 LifecycleListener

2)RequestManager.load(url) 創建了一個 RequestBuilder<T>對象 T 可以是 Drawable 對象或是 ResourceType

3 ) RequestBuilder.into(view)-->into(glideContext.buildImageViewTarget(view, transcodeClass))返 回 的 是 一 個DrawableImageViewTarget, Target 用 來 最 終 展 示 圖 片 的 ,buildImageViewTarget-->ImageViewTargetFactory.buildTarget()根據傳入 class 參數不同構建不同的 Target 對象,這個 Class 是根據構建 Glide 時是否調用了 asBitmap()方法,如果調用了會構建出BitmapImageViewTarget,否則構建的是GlideDrawableImageViewTarget 對象。
-->GenericRequestBuilder.into(Target), 該 方 法 進 行 了 構 建 Request , 并 用RequestTracker.runRequest()-->GenericRequest.begin()

 Request request = buildRequest(target);
         // 構建 Request 對象, 
        target.setRequest(request);
        lifecycle.addListener(target);
 requestTracker.runRequest(request);
       // 判斷 Glide 當前是不是處于暫停狀態

onSizeReady()--> `Engine.load(signature, width, height, dataFetcher, loadProvider,transformation, transcoder,priority, isMemoryCacheable, diskCacheStrategy, this)

a)先構建EngineKey;

b)`loadFromCache 從 緩 存 中 獲 取 EngineResource , 如 果 緩 存 中 獲 取 到 cache 就 調 用`cb.onResourceReady(cached);

c)如果緩存中不存在調用loadFromActiveResources從 active中獲取,如果獲取到就調用cb.onResourceReady(cached);

d)如果 active 中也不存在,調用EngineJob.start(EngineRunnable), 從而調用decodeFromSource()/decodeFromCache()-->如果是調 用decodeFromSource()-->ImageVideoFetcher.loadData()-->HttpUrlFetcher()調 用HttpUrlConnection進 行 網 絡 請 求 資 源 --> 得 于InputStream()后 , 調 用decodeFromSourceData()-->loadProvider.getSourceDecoder().decode() 方 法 解 碼-->GifBitmapWrapperResourceDecoder.decode()-->decodeStream()先從流中讀取 2 個字節判斷是 GIF 還是普通圖,若是 GIF 調用decodeGifWrapper()來解碼,若是普通靜圖則調用decodeBitmapWrapper()來解碼-->bitmapDecoder.decode()`

三丶Glide 使用什么緩存?

1) 內存緩存: LruResourceCache(memory)+弱引用 activeResources
Map<Key, WeakReference<EngineResource<?>>> activeResources正在使用的資源,當 acquired變量大于 0,說明圖片正在使用,放到 activeResources 弱引用緩存中,經過 release()后,acquired=0,說明圖片不再使用,會把它放進 LruResourceCache

2)磁盤緩存: DiskLruCache,這里分為 Source(原始圖片)和 Result(轉換后的圖片)

第一次獲取圖片,肯定網絡取,然后存 active\disk 中,再把圖片顯示出來,第二次讀取相同的圖片,并加載到相同大小的 imageview 中,會先從 memory 中取,沒有再去 active 中獲取。如果 activity 執行到 onStop 時,圖片被回收,active 中的資源會被保存到memory 中,active中的資源被回收。當再次加載圖片時,會從 memory 中取,再放入 active 中,并將 memory中對應的資源回收。

之所以需要 activeResources,它是一個隨時可能被回收的資源,memory 的強引用頻繁讀寫可能造成內存激增頻繁 GC,而造成內存抖動。資源在使用過程中保存在 activeResources 中,而 activeResources 是弱引用,隨時被系統回收,不會造成內存過多使用和泄漏。

四丶Glide 內存緩存如何控制大小?

Glide 內存緩存最大空間(maxSize)=每個進程可用最大內存0.4(低配手機是 每個進程可用最大內存0.33)

磁盤緩存大小是 250MB int DEFAULT_DISK_CACHE_SIZE = 250 1024 1024;

五丶LruCache 底層實現原理:

LruCacheLru 算法的實現就是通過 LinkedHashMap 來實現的。LinkedHashMap繼承于HashMap,它使用了一個雙向鏈表來存儲 Map 中的 Entry 順序關系,對于 get、put、remove 等操作,LinkedHashMap 除了要做 HashMap 做的事情,還做些調整 Entry 順序鏈表的工作。

LruCache 中將 LinkedHashMap 的順序設置為 LRU 順序來實現 LRU 緩存,每次調用 get(也就是從內存緩存中取圖片),則將該對象移到鏈表的尾端。調用 put 插入新的對象也是存儲在鏈表尾端,這樣當內存緩存達到設定的最大值時,將鏈表頭部的對象(近期最少用到的)移除。

六丶三級緩存原理

當 Android 端需要獲得數據時比如獲取網絡中的圖片,首先從內存中查找(按鍵查找),內存中沒有的再從磁盤文件或 sqlite 中去查找,若磁盤中也沒有才通過網絡獲取

七丶如何設計一個大圖加載框架

圖片加載包含封裝,解析,下載,解碼,變換,緩存,顯示等操作

  • 封裝參數: 從指定來源,到輸出結果,中間可能經歷很多流程,所以第一件事就是封裝參數,這些參數會貫穿整個過程;
  • 解析路徑: 圖片的來源有多種,格式也不盡相同,需要規范化;
  • 讀取緩存: 為了減少計算,通常都會做緩存;同樣的請求,從緩存中取圖片(Bitmap)即可;
  • 查找文件/下載文件: 如果是本地的文件,直接解碼即可;如果是網絡圖片,需要先下載;
  • 解碼: 這一步是整個過程中最復雜的步驟之一,有不少細節,下個博客會說;
  • 變換: 解碼出Bitmap之后,可能還需要做一些變換處理(圓角,濾鏡等);
  • 緩存: 得到最終bitmap之后,可以緩存起來,以便下次請求時直接取結果;
  • 顯示: 顯示結果,可能需要做些動畫(淡入動畫,crossFade等)
    原來面試的時候寫精通Glide,這樣問我這樣答
    請查看完整的PDF版
    (更多完整項目下載。未完待續。源碼。圖文知識后續上傳github。)
    可以點擊關于我聯系我獲取完整PDF
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

电白县| 许昌市| 株洲县| 洱源县| 山阳县| 古丈县| 沈阳市| 墨玉县| 旌德县| 鹤庆县| 陈巴尔虎旗| 江达县| 浮山县| 宁津县| 马山县| 河曲县| 金溪县| 连平县| 射洪县| 色达县| 营山县| 田阳县| 濮阳县| 永丰县| 通辽市| 宁城县| 大姚县| 丰顺县| 隆化县| 和田县| 象州县| 龙岩市| 宁陕县| 建阳市| 邯郸市| 洛扎县| 乌审旗| 石阡县| 安国市| 海口市| 大姚县|