1. 程式人生 > >Glide原始碼(基於4.8版本)解析

Glide原始碼(基於4.8版本)解析

Glide是一款由Bump Technologies開發的圖片載入框架,使得我們可以在Android平臺上以極度簡單的方式來載入和展示圖片。
 使用Glide來載入網路圖片非常簡單,通過Glide.with(this).load(url).into(imageView)這樣的一句程式碼就可以搞定,雖然很簡單,但還是需要知其所以然。下面就來梳理一下Glide是如何載入網路圖片(不涉及生命週期、快取等功能點,僅載入網路圖片的實現)。

Glide.with(context)

 由於本文不涉及Glide的生命週期,所以直接來看Glide構造方法。

  Glide(
      @NonNull
Context context, @NonNull Engine engine, @NonNull MemoryCache memoryCache, @NonNull BitmapPool bitmapPool, @NonNull ArrayPool arrayPool, @NonNull RequestManagerRetriever requestManagerRetriever, @NonNull ConnectivityMonitorFactory connectivityMonitorFactory, int
logLevel, @NonNull RequestOptions defaultRequestOptions, @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) { this.engine = engine; this.bitmapPool = bitmapPool; this.arrayPool = arrayPool; this.memoryCache = memoryCache; this
.requestManagerRetriever = requestManagerRetriever; this.connectivityMonitorFactory = connectivityMonitorFactory; DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT); bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat); final Resources resources = context.getResources(); //管理元件註冊以擴充套件或替換Glide的預設載入,解碼和編碼邏輯。 registry = new Registry(); // Right now we're only using this parser for HEIF images, which are only supported on OMR1+. // If we need this for other file types, we should consider removing this restriction. // Note that order here matters. We want to check the ExifInterface parser first for orientation // and then fall back to DefaultImageHeaderParser for other fields. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { registry.register(new ExifInterfaceImageHeaderParser()); } registry.register(new DefaultImageHeaderParser()); Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(), resources.getDisplayMetrics(), bitmapPool, arrayPool); ByteBufferGifDecoder byteBufferGifDecoder = new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool); ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder = VideoDecoder.parcel(bitmapPool); ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler); StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool); ResourceDrawableDecoder resourceDrawableDecoder = new ResourceDrawableDecoder(context); ResourceLoader.StreamFactory resourceLoaderStreamFactory = new ResourceLoader.StreamFactory(resources); ResourceLoader.UriFactory resourceLoaderUriFactory = new ResourceLoader.UriFactory(resources); ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory = new ResourceLoader.FileDescriptorFactory(resources); ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory = new ResourceLoader.AssetFileDescriptorFactory(resources); BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool); BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder(); GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder(); ContentResolver contentResolver = context.getContentResolver(); registry .append(ByteBuffer.class, new ByteBufferEncoder()) .append(InputStream.class, new StreamEncoder(arrayPool)) /* Bitmaps */ .append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder) .append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder) .append( Registry.BUCKET_BITMAP, ParcelFileDescriptor.class, Bitmap.class, parcelFileDescriptorVideoDecoder) .append( Registry.BUCKET_BITMAP, AssetFileDescriptor.class, Bitmap.class, VideoDecoder.asset(bitmapPool)) .append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance()) .append( Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder()) .append(Bitmap.class, bitmapEncoder) /* BitmapDrawables */ .append( Registry.BUCKET_BITMAP_DRAWABLE, ByteBuffer.class, BitmapDrawable.class, new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder)) .append( Registry.BUCKET_BITMAP_DRAWABLE, InputStream.class, BitmapDrawable.class, new BitmapDrawableDecoder<>(resources, streamBitmapDecoder)) .append( Registry.BUCKET_BITMAP_DRAWABLE, ParcelFileDescriptor.class, BitmapDrawable.class, new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder)) .append(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, bitmapEncoder)) /* GIFs */ .append( Registry.BUCKET_GIF, InputStream.class, GifDrawable.class, new StreamGifDecoder(registry.getImageHeaderParsers(), byteBufferGifDecoder, arrayPool)) .append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder) .append(GifDrawable.class, new GifDrawableEncoder()) /* GIF Frames */ // Compilation with Gradle requires the type to be specified for UnitModelLoader here. .append( GifDecoder.class, GifDecoder.class, UnitModelLoader.Factory.<GifDecoder>getInstance()) .append( Registry.BUCKET_BITMAP, GifDecoder.class, Bitmap.class, new GifFrameResourceDecoder(bitmapPool)) /* Drawables */ .append(Uri.class, Drawable.class, resourceDrawableDecoder) .append( Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitmapPool)) /* Files */ .register(new ByteBufferRewinder.Factory()) .append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory()) .append(File.class, InputStream.class, new FileLoader.StreamFactory()) .append(File.class, File.class, new FileDecoder()) .append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory()) // Compilation with Gradle requires the type to be specified for UnitModelLoader here. .append(File.class, File.class, UnitModelLoader.Factory.<File>getInstance()) /* Models */ .register(new InputStreamRewinder.Factory(arrayPool)) .append(int.class, InputStream.class, resourceLoaderStreamFactory) .append( int.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory) .append(Integer.class, InputStream.class, resourceLoaderStreamFactory) .append( Integer.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory) .append(Integer.class, Uri.class, resourceLoaderUriFactory) .append( int.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory) .append( Integer.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory) .append(int.class, Uri.class, resourceLoaderUriFactory) .append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>()) .append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>()) .append(String.class, InputStream.class, new StringLoader.StreamFactory()) .append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory()) .append( String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory()) .append(Uri.class, InputStream.class, new HttpUriLoader.Factory()) .append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets())) .append( Uri.class, ParcelFileDescriptor.class, new AssetUriLoader.FileDescriptorFactory(context.getAssets())) .append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context)) .append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context)) .append( Uri.class, InputStream.class, new UriLoader.StreamFactory(contentResolver)) .append( Uri.class, ParcelFileDescriptor.class, new UriLoader.FileDescriptorFactory(contentResolver)) .append( Uri.class, AssetFileDescriptor.class, new UriLoader.AssetFileDescriptorFactory(contentResolver)) .append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory()) .append(URL.class, InputStream.class, new UrlLoader.StreamFactory()) .append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context)) //進行網路下載 .append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory()) .append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory()) .append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory()) .append(Uri.class, Uri.class, UnitModelLoader.Factory.<Uri>getInstance()) .append(Drawable.class, Drawable.class, UnitModelLoader.Factory.<Drawable>getInstance()) .append(Drawable.class, Drawable.class, new UnitDrawableDecoder()) /* Transcoders */ .register( Bitmap.class, BitmapDrawable.class, new BitmapDrawableTranscoder(resources)) .register(Bitmap.class, byte[].class, bitmapBytesTranscoder) .register( Drawable.class, byte[].class, new DrawableBytesTranscoder( bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder)) .register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder); ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory(); glideContext = new GlideContext( context, arrayPool, registry, imageViewTargetFactory, defaultRequestOptions, defaultTransitionOptions, engine, logLevel); }

 構造方法最重要的就是Register這個類,它主要是用於管理元件註冊以擴充套件或替換Glide的預設載入,解碼和編碼邏輯,比如我們可以使用giflib替換Glide自帶的GIF解碼器,來提高效能,也可以使用OKHttp來替換Glide預設的下載實現等。構造方法裡預設註冊了HttpGlideUrlLoader這個類,為什麼要說這個類尼,因為預設的下載功能就在裡面。
with是Glide的一組靜態方法,它裡面有關於Glide生命週期的實現。來看看這組靜態方法的實現。

  public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }
  ...

 從上面可以看出with都返回了一個RequestManager物件。

load(url)

loadRequestManager裡的一組方法,根據傳入引數來不同的實現,這裡就以傳入一個字串的url為例。

  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
  //這裡代表返回一個Drawable型別的圖片
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  //建立一個RequestBuilder物件。
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    //resourceClass對應著RequestBuilder的transcodeClass變數
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

RequestBuilder物件建立成功後,在呼叫load方法將圖片路徑賦值給model這個變數。

into(imageView)

 前面快速介紹了Glide.with(context)load(url)的實現,雖然它們也並不簡單(生命週期模組未介紹),但它們也沒有實現圖片的下載,那麼圖片的下載是從哪裡開始的尼?就是通過into方法來實現的,來看一下into方法的實現。

  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    ...
    return into(
        //transcodeClass就是前面傳遞過來的Drawable.class
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);
  }

 由於transcodeClass是一個Drawable型別,所以glideContext.buildImageViewTarget(view, transcodeClass)建立了一個DrawableImageViewTarget物件,來看看DrawableImageViewTarget的實現。

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {

  public DrawableImageViewTarget(ImageView view) {
    super(view);
  }

  /**
   * @deprecated Use {@link #waitForLayout()} instead.
   */
  // Public API.
  @SuppressWarnings({"unused", "deprecation"})
  @Deprecated
  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
    super(view, waitForLayout);
  }
  //這裡是不是很熟悉啊,就是展示圖片
  
            
           

相關推薦

Glide原始碼基於4.8版本解析

 Glide是一款由Bump Technologies開發的圖片載入框架,使得我們可以在Android平臺上以極度簡單的方式來載入和展示圖片。  使用Glide來載入網路圖片非常簡單,通過Glide.with(this).load(url).into(imageView)這樣的一句程式碼

Sentinel Dashboard基於1.8.1流控規則持久化到Nacos——涉及部分Sentinel Dashboard原始碼改造

前言   之前雖然也一直在使用sentinel實現限流熔斷功能,但卻沒有好好整理之前看的原始碼與資料,今天有時間將之前自己整理過的資料寫成一篇博文,或者是是一篇關於Sentinel(基於目前最近版本1.8,如果沒有特殊說明,都指最新1.8版本)持久化Nacos的指南,因為我發現網上的一些博文雖然有參考價值但

Disconf 學習系列之全網最詳細的最新穩定Disconf 搭建部署基於Windows7 / 8 / 10圖文詳解

分享 study str www windows 最新 1.8 環境 text   不多說,直接上幹貨! 工作環境以及安裝依賴軟件 Zookeeper-3.4.8 Disconf 2.6.36 Nginx 1.9.9(見如下博文的phpstu

springcloud的Hystrix turbine斷路器聚合監控實現基於springboot2.02版本

events 單個 res source IE lease ans discover www 本文基於方誌朋先生的博客實現:https://blog.csdn.net/forezp/article/details/70233227 一、準本工作 1、工具:Idea,JD

vue.js篩選功能基於1.0版本

<!DOCTYPE html> <html lang="zh">     <head>         <meta charset="UTF-8" />         <meta name="viewport" con

NMT-nametus入門瞭解基於TensorFlow的版本

1、首先看github上的readme: NEMATUS Attention-based encoder-decoder model for neural machine translation //基於注意力編碼解碼 模型 This package is ba

Redis安裝及配置基於5.0版本

目前最新版為:5.0.3,官方推薦使用原始碼方式進行安裝,以下是安裝步驟: 1、下載 wget http://download.redis.io/releases/redis-5.0.3.tar.gz 2、解壓 tar -xzvf redis-5.0.3.tar.gz -C

Python中關於URL的處理基於Python2.7版本

參考官方文件:https://docs.python.org/3/library/urllib.html點選開啟連結1、 完整的url語法格式: 協議://使用者名稱@密碼:子域名.域名.頂級域名:埠

Glide 系列-2:主流程原始碼分析4.8.0

Glide 是 Android 端比較常用的圖片載入框架,這裡我們就不再介紹它的基礎的使用方式。你可以通過檢視其官方文件學習其基礎使用。這裡,我們給出一個 Glide 的最基本的使用示例,並以此來研究這個整個過程發生了什麼: Glide.with(fragment).load(myU

菜鳥帶你看原始碼——看不懂你打我ArrayList原始碼分析基於java 8

文章目錄 看原始碼並不難 軟體環境 成員變數: 構造方法 核心方法 get方法 remove方法 add方法 結束 看原始碼並不難 如何學好程式設計?如何寫出優質的程式碼?如

使用Hbase協作器(Coprocessor)同步資料到ElasticSearchhbase 版本 1.2.0-cdh5.8.0, es 2.4.0 版本

參考 https://gitee.com/eminem89/Hbase-Observer-ElasticSearch 上面的程式碼,但是由於我的es版本是2.4.0 和作者的版本不對應導致功能無法正常使用,所以特此記錄修改成能參考   程式碼如

java集合之----ArrayList原始碼分析基於jdk1.8

一、ArrayList 1、ArrayList是什麼: ArrayList就是動態陣列,用MSDN中的說法,就是Array的複雜版本,它提供了動態的增加和減少元素,實現了ICollection和IList介面,靈活的設定陣列的大小等好處,實現了Randomaccess介面,支援快速隨

JAVA常用集合框架原始碼解析基於1.8開題篇

倪升武的部落格中有一個小專題,讀完之後,發現博主的分析基本是基於JAVA1.7的,這裡我基於JAVA1.8給出一些新的解讀。但是對於JAVA1.8新增的一些新特性可能不太會作過多的分析(畢竟本人目前水平有限,且本部落格的寫作初衷也是以基礎學習為主),在徹底淺讀完

WeakHashMap原始碼探討基於JDK1.8

WeakHashMap簡介 WeakHashMap跟普通的HashMap不同,WeakHashMap的行為一定程度上基於垃圾收集器的行為,因此一些Map資料結構對應的常識在WeakHashMap上會失效——size()方法的返回值會隨著程式的執行變小,isE

HashSet原始碼探討基於JDK1.8

HashSet 簡介 如果對HashMap沒有了解,應該先學習HashMap再學習HashSet 。 HashSet結構 publicclassHashSet<E>extendsA

Glide 系列-3:Glide 快取的實現原理4.8.0

1、在 Glide 中配置快取的方式 首先,我們可以在自定義的 GlideModule 中制定詳細的快取策略。即在 applyOptions() 中通過直接呼叫 GlideBuilder 的方法來指定快取的資訊: @Override public void applyOptions(@No

JAVA集合原始碼解析 Hashtable探索基於JDK1.8

JDK1.8Hashtable探索 本文的討論分析是基於JDK1.8進行的 依舊是採用前幾篇文章的大綱來進行介紹 1.簡介 Hashtable 採用陣列+單鏈表來實現的,Hashtable 實現了一個雜湊表,它將鍵對映到值。任何非 nu

ButterKnife8.4.0版本原理分析

        ButterKnife是鼎鼎大名的JakeWharton寫的註解框架, 將你從findViewById這樣無聊的體力活解脫出來。  github地址: https://github.com/JakeWharton/butterknife  , 已超過1萬顆星

[區塊鏈]Hyperledger Fabric原始碼基於v1.0 beta版本閱讀之樂扣老師解讀系列 BCCSP包之工廠包

核心包之BCCSP(區塊鏈加密服務提供者)包之factory工廠包 首先,我們看其程式碼結構: 主要包含factory工廠包,mocks模擬測試包,加解密關聯包pkcs11、signer簽名包、sw加解密實現包以及工具包utils。 根據整個結構我們對

HashMap原始碼分析基於1.8

HashMap1.7和1.8變動比較多。 關於HashMap 1.7的版本,倪升武的部落格總結的很好。 這裡我主要來介紹一下1.8中的HashMap。由於HashMap原始碼太長,我只挑選了部分進行分析,如果有沒有分析到的重點難點或者大家有疑問的地方,希望大