Glide4.10加載網絡圖片的基本流程

Glide4.10 加載網絡圖片的基本流程

Glide.with(context).load(url).into(imageView);
加載一張圖片,主要經過上面三個步驟; 下面會逐個分析三個步驟;
本文針對的Glide 4.10版本;

第1步:with(context) 生成RequestManager對象

  1. 根據context是否是Application,Glide決定是否需要關注頁面的生命週期;
  2. Glide通過添加一個空Fragment的方式感知生命週期變化;

第2步:load(url) 生成RequestManager對象

  • 大部分api在這個階段添加到RequestManager, 比如listener();
  • 該階段指定了model類型,本例中model是String類型的url;

第3步:into(imageView)

  1. 首先,使用imageView構造Target,into()主要任務:創建並且執行 Request: requestManager.track(target, request);
  2. 隨後,執行Request的begin()方法, 本例爲SingleRequest對象的begin()
  3. 執行Target的getSize()指定所需寬高;此時自定義Target可以設置想要的寬高;
  4. 最後,執行SingleRequest的onSizeReady(), 調用Engine對象的load()方法開始加載;

第3.1步驟: Engine.load() 加載圖片

  • 首先試圖從內存緩存(內存緩存分兩級)中取,loadFromMemory() 步驟:
    • loadFromActiveResources():根據Key從ActivieResources集合獲取;
      • ActivieResources爲1級內存緩存,存儲當前Activity正在使用的資源;
    • loadFromCache():再從MemoryCache中獲取;
      • MemoryCache爲2級內存緩存,該接口的實現類爲LruResourceCache;
  • 如果loadFromMemory() 沒獲取到緩存Resource,則從文件緩存或者數據源獲取;
  • Engine對象waitForExistingOrStartNewJob()創建EngineJob和DecodeJob;
    • EngineJob是從Pools.Pool<EngineJob<?>> pool對象池獲取;DecodeJob類似;
    • DecodeJob繼承自Runnable;EngineJob會啓動DecodeJob;
  • DecodeJob的run()方法,核心邏輯在DecodeJob的runWrapped()方法;
  • runWrapped()方法,主要通過狀態機runReason控制;
  • 首先將狀態機runReason初始爲RunReason.INITIALIZE;
  • 執行getNextGenerator()獲取DataFetcherGenerator;
    • DataFetcherGenerator接口用來獲取數據,它有三個具體實現類:
      • ResourceCacheGenerator:獲取downsampled/transformed的資源數據;
      • DataCacheGenerator:獲取原始未修改過的資源數據;
      • SourceGenerator:意味着從原始數據源獲取數據;
    • 依次查詢上面3個實現類;本例爲第一次獲取圖片情形,currentGenerator最終爲SourceGenerator,即需要從Source中取數據;
  • 執行currentGenerator的startNext(),核心邏輯:尋找合適的LoadData,進而生成Fetcher,執行Fetcher的loadData()方法獲取InputStream;
    • 從ModelLoader集合中尋找合適的ModelLoader,依據是boolean handles(Model), 該方法返回true表示可以處理該Model;
      • Glide對象初始化時註冊所有ModelLoader,將其存儲在Registry對象中;
        • ModelLoader列表可以通過GlideContext獲取;
      • 本例爲加載網絡圖片,Loader爲HttpUriLoader,因爲它的handles()方法是判斷scheme是否爲http或https;
    • HttpUriLoader的model是Uri類型,它將model包裝爲GlideUrl類型,將load工作交給HttpGlideUrlLoader的buildLoadData()
    • HttpGlideUrlLoader的buildLoadData()創建用於網絡通信的HttpUrlFetcher對象;網絡通信的結果是InputStream, 隨後需要將其decode爲Resource;
    • fetcher拿到IS後,回調DecodeJob的onDataFetcherReady(Key, Resource ...)
  • DecodeJob通過回調拿到fetcher,執行decodeFromRetrievedData()解碼,拿到Resource對象;
    • 執行decodeFromData() 獲取Resource, 具體邏輯在decodeFromFetcher():
      • decodeHelper.getLoadPath()獲取LoadPath;
        • 首先通過getDecodePaths()獲取DecodePath列表;
          • DecodePath和ModelLoader類似,都是註冊在Registry,也是通過handles()方法判斷;
        • 本例的DecodePath列表中只包含ByteBufferBitmapDecoder;
        • 使用DecodePath列表創建並返回一個LoadPath:
      • 執行LoadPath的runLoadPath()方法:返回Resource;
        • 遍歷DecodePath列表,調用DecodePath.decodeResource()進行解碼;
        • 解碼完成後,回調DecodeJob的onResourceDecoded(), 執行Transform、緩存等操作;
        • 本例Resource爲Bitmap, 實際上Bitmap/Drawable/Gif等都實現Resource接口;
    • 拿到Resource後,調用DecodeJob的notifyEncodeAndRelease();
    • 回調EngineJob的onResourceReady(Resource) ,進一步執行notifyCallbacksOfResult():
      • 回調Engine的onEngineJobComplete(),將Resource保存到內存緩存中;
      • 回調SingleRequest的onResourceReady()回調listener(new RequestListener)中邏輯;
  • SingleRequest回調Target的同名方法onResourceReady(),完成最終的顯示;
    • 本例執行into(ImageView),則會執行ImageViewTarget的onResourceReady()
    • ImageViewTarget的onResourceReady()調用抽象方法setResource(Resource),如果執行過asBitmap(), 便執行BitmapImageViewTarget的setResource(),具體爲view.setImageBitmap(resource);
  • 此時圖片便加載出來了;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章