Glide4用法全解析(一)——RequestBuilder

時代不變發表於2020-04-07

使用準備

新增依賴

implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
複製程式碼

許可權

<uses-permission android:name="android.permission.INTERNET" />
<!--非必需-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
複製程式碼

ACCESS_NETWORK_STATE 對於 Glide 載入 URL 並不是必需的,但是它將幫助 Glide 處理 片狀網路(flaky network) 和飛航模式。如果你正在從 URL 載入圖片,Glide 可以自動幫助你處理片狀網路連線:它可以監聽使用者的連線狀態並在使用者重新連線到網路時重啟之前失敗的請求。如果 Glide 檢測到你的應用擁有 ACCESS_NETWORK_STATE 許可權,Glide 將自動監聽連線狀態而不需要額外的改動

如果要使用 ExternalPreferredCacheDiskCacheFactory 來將 Glide 的快取儲存到公有 SD 卡上,就需要新增 WRITE_EXTERNAL_STORAGE 許可權。

混淆

-dontwarn com.bumptech.glide.**
-keep class com.bumptech.glide.**{*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
複製程式碼

Kotlin

如果你在 Kotlin 編寫的類裡使用 Glide 註解,你需要引入一個 kapt 依賴,以代替常規的 annotationProcessor 依賴:

dependencies {
  kapt 'com.github.bumptech.glide:compiler:4.8.0'
}
複製程式碼

還需要在你的 build.gradle 檔案中包含 kotlin-kapt外掛: apply plugin: 'kotlin-kapt'

RequestBuilder

RequestBuilder是Glide中請求的骨架,負責攜帶請求的url和你的設定項來開始一個新的載入過程。 RequestBuilder的來源如下:

RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).asDrawable();
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment).load("url");
RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();
RequestBuilder<GifDrawable> requestBuilder = Glide.with(fragment).asGif();
RequestBuilder<File> requestBuilder = Glide.with(fragment).asFile();
複製程式碼

使用

 Glide.with(this)
    .load("url")
    .apply()//設定請求選項
    .transition()//設定過渡
    .thumbnail()//略縮圖相關
    .error()//請求出錯相關
    .listener()或addListener//監聽
    .into()或submit()//指定目標
複製程式碼

RequestOptions

RequestOptions cropOptions = new RequestOptions().centerCrop();
Glide.with(fragment)
    .load(url)
    .apply(cropOptions)
    .into(imageView);
複製程式碼

RequestOptions用來提供獨立的選項來定製Glide載入。由於apply() 方法可以被呼叫多次,因此 RequestOption 可以被組合使用。如果 RequestOptions 物件之間存在相互衝突的設定,那麼只有最後一個被應用的 RequestOptions 會生效。

常用的api如下:

佔點陣圖

佔位符是當請求正在執行時被展示的 Drawable 。當請求成功完成時,佔位符會被請求到的資源替換

  • placeholder():佔點陣圖,如果請求失敗並且沒有設定 error Drawable ,則佔位符將被持續展示
  • error():異常佔點陣圖,在請求永久性失敗時展示
  • fallback:後備回撥符,在請求的url為 null 時展示

設計 fallback Drawable 的主要目的是允許使用者指示 null 是否為可接受的正常情況。例如,一個 null 的個人資料 url 可能暗示這個使用者沒有設定頭像,因此應該使用預設頭像。然而,null 也可能表明這個後設資料根本就是不合法的,或者取不到。 預設情況下Glide將 null 作為錯誤處理,所以可以接受 null 的應用應當顯式地設定一個 fallback Drawable 。

//placeholder()
Glide.with(fragment)
  .load(url)
  .placeholder(R.drawable.placeholder)
//.placeholder(new ColorDrawable(Color.BLACK))
  .into(view);

//error()
Glide.with(fragment)
  .load(url)
  .error(R.drawable.error)
//.error(new ColorDrawable(Color.RED))
  .into(view);

//fallback
Glide.with(fragment)
  .load(url)
  .fallback(R.drawable.fallback)
//.fallback(new ColorDrawable(Color.GREY))
  .into(view);
複製程式碼

注意:

  • 佔位符是在主執行緒從Android Resources載入的
  • 變換不會被應用到佔位符上
  • 在多個不同的View上可以使用相同的無狀態的Drawable;但是有狀態的 Drawable 不一樣,在同一時間多個 View 上展示它們通常不是很安全,因為多個View會立刻修改(mutate) Drawable 。對於有狀態的 Drawable ,建議傳入一個資源ID,或者使用 newDrawable() 來給每個請求傳入一個新的拷貝。

diskCacheStrategy()

用來設定硬碟快取,可選項如下:

  • DiskCacheStrategy.NONE: 表示不快取任何內容。
  • DiskCacheStrategy.DATA: 表示只快取原始圖片。
  • DiskCacheStrategy.RESOURCE: 表示只快取轉換過後的圖片。
  • DiskCacheStrategy.ALL : 表示既快取原始圖片,也快取轉換過後的圖片。
  • DiskCacheStrategy.AUTOMATIC:表示讓Glide根據圖片資源智慧地選擇使用哪一種快取策略(預設選項)

skipMemoryCache(boolean)

  • true :跳過記憶體快取
  • false :不跳過記憶體快取

變換

預設變換

  • centerCrop():以填滿整個控制元件為目標,等比縮放,超過控制元件時將被 裁剪 ( 寬高都要填滿 ,所以只要圖片寬高比與控制元件寬高比不同時,一定會被剪裁)
  • centerInside():以完整顯示圖片為目標, 不剪裁 ,當顯示不下的時候將縮放,能夠顯示的情況下不縮放
  • fitCenter():將圖片按照原始的長寬比充滿全屏
  • circleCrop():圓形裁剪
  • transform():設定自定義圖片變換

optionalCenterCrop()optionalCenterInside()optionalFitCenter()optionalCircleCrop()centerCrop()centerInside()fitCenter()circleCrop()的區別:centerCrop()等對未知型別圖片進行變換時會丟擲異常,而optionalCenterCrop()則會忽略未知的圖片型別。

多重變換

transform(new MultiTransformation<>(new CenterCrop(),new CircleCrop()))
transforms(new CenterCrop(),new CircleCrop())
複製程式碼

傳入變換引數的順序,決定了這些變換的應用順序

自定義變換

自定義變換需要繼承BitmapTransformation(也可以繼承Transformation),並重寫下面方法:

equals
hashCode
updateDiskCacheKey
transform
複製程式碼

下面是CircleCrop的原始碼

public class CircleCrop extends BitmapTransformation {
  private static final int VERSION = 1;
  private static final String ID = "com.bumptech.glide.load.resource.bitmap.CircleCrop." + VERSION;
  private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

  // Bitmap doesn't implement equals, so == and .equals are equivalent here.
  @SuppressWarnings("PMD.CompareObjectsWithEquals")
  @Override
  protected Bitmap transform(
      @NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
    return TransformationUtils.circleCrop(pool, toTransform, outWidth, outHeight);
  }

  @Override
  public boolean equals(Object o) {
    return o instanceof CircleCrop;
  }

  @Override
  public int hashCode() {
    return ID.hashCode();
  }

  @Override
  public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
    messageDigest.update(ID_BYTES);
  }
}
複製程式碼

glide-transformations是一個優秀的自定義變換庫,該庫的效果如圖

Glide4用法全解析(一)——RequestBuilder

override()

用來指定了一個圖片的尺寸(單位px),可以用Target.SIZE_ORIGINAL表示載入原始尺寸的圖片,但這會產生OOM的風險。

TransitionOptions

TransitionOptions 用於決定你的載入完成時從佔點陣圖到目標圖過渡之間會發生什麼。

不同於 Glide v3,Glide v4 將不會預設應用交叉淡入或任何其他的過渡效果。每個請求必須手動應用過渡。

Glide.with(this)
    .load("")
    .transition(DrawableTransitionOptions.withCrossFade())
    .into(imageView);
複製程式碼
  • GenericTransitionOptions:通用的過渡選項
  • DrawableTransitionOptions:只應用於Glide呼叫了asDrawable()(預設)方法時,才能使用
  • BitmapTransitionOptions:只應用於Glide呼叫asBitmap()方法時,才能使用

Glide中只實現了淡入淡出的過渡效果,即呼叫DrawableTransitionOptionsBitmapTransitionOptionswithCrossFade()方法,如果需要自定義過渡效果,則必需實現TransitionFactory ,並且 使用 DrawableTransitionOptionsBitmapTransitionOptionswith方法來將你自定義的 TransitionFactory 應用到載入中。

略縮圖(thumbnail)

//thumbnail()方法可以簡單快速地載入影像的低解析度版本,並且同時載入影像的無損版本
Glide.with(this)
    .asDrawable()
    .load("url")
    .thumbnail(Glide.with(this).load("thumbnailUrl"))
    .into(imageView);
//載入同一個圖片,但尺寸為 View 或 Target 的某個百分比的(這裡為0.25)
Glide.with(this)
    .asDrawable()
    .load("url")
    .thumbnail(0.25f)
    .into(imageView);
複製程式碼

error

Glide.with(fragment)
  .load("url")
  .error(Glide.with(fragment)
      .load("errorUrl"))
  .into(imageView);
複製程式碼

在失敗時開始新的請求。如果主請求成功完成,則這個error請求 將不會被啟動。如果你同時指定了一個 thumbnail() 和一個 error請求,則這個後備的 error請求將在主請求失敗時啟動,即使縮圖請求成功也是如此。

listener和addListener

Glide.with(this)
    .load("url")
    .listener(new RequestListener<Drawable>() {
        @Override
        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
            return false;
        }

        @Override
        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
            return false;
        }
    })
    .into(imageView);
複製程式碼

RequestListener需要實現兩個方法,一個onResourceReady()方法,一個onLoadFailed()方法。當圖片載入完成的時候就會回撥onResourceReady()方法,而當圖片載入失敗的時候就會回撥onLoadFailed()方法。onResourceReady()方法和onLoadFailed()方法都有一個布林值的返回值,返回false就表示這個事件沒有被處理,還會繼續向下傳遞,返回true就表示這個事件已經被處理掉了,從而不會再繼續向下傳遞。

與Glide的listener類似的還有一個addListener方法,它們的區別在於,當呼叫多個listener方法時,只會呼叫最後的listener回撥;而addListener方法會依次呼叫多個addListener設定的回撥。

into和summit

  • into():下載圖片,並把資源載入到指定目標上
  • submit():只會下載圖片,而不會對圖片進行載入

呼叫了submit()方法後會立即返回一個FutureTarget物件,然後Glide會在後臺開始下載圖片檔案。之後我們呼叫FutureTargetget()方法就可以去獲取下載好的圖片檔案了,注意:get()方法會阻塞當前執行緒,直到下載完成

參考

相關文章