Android圖片快取之Glide進階

總李寫程式碼發表於2016-06-06

前言:

     前面學習了Glide的簡單使用(Android圖片快取之初識Glide),今天來學習一下Glide稍微複雜一點的使用。

 圖片快取相關部落格地址:

GlideModule使用:

       GlideModule 是一個抽象方法,全域性改變 Glide 行為的一個方式,通過全域性GlideModule 配置Glide,用GlideBuilder設定選項,用Glide註冊ModelLoader等。

  1.)自定義一個GlideModule 

public class MyGlideModule implements GlideModule {
    @Override public void applyOptions(Context context, GlideBuilder builder) {
        // Apply options to the builder here.
    }

    @Override public void registerComponents(Context context, Glide glide) {
        // register ModelLoaders here.
    }
}

  2.)AndroidManifest.xml註冊

<manifest ...>
    <!-- ... permissions -->
    <application ...>
        <meta-data
            android:name="com.mypackage.MyGlideModule"
            android:value="GlideModule" />
        <!-- ... activities and other components -->
    </application>
</manifest>

  3.)新增混淆處理

-keepnames class com.mypackage.MyGlideModule
# or more generally:
#-keep public class * implements com.bumptech.glide.module.GlideModule

  4.)多個GlideModule衝突問題

   GlideModule不能指定呼叫順序,所以應該避免不同的GlideModule之間有衝突的選項設定,可以考慮將所有的設定都放到一個GlideModule裡面,或者排除掉某個manifest檔案的某個Module,程式碼如下:

<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”remove” />

GlideBuilder設定選項:

1.)設定Glide記憶體快取大小

 int maxMemory = (int) Runtime.getRuntime().maxMemory();//獲取系統分配給應用的總記憶體大小
 int memoryCacheSize = maxMemory / 8;//設定圖片記憶體快取佔用八分之一
 //設定記憶體快取大小
 builder.setMemoryCache(new LruResourceCache(memoryCacheSize));

  獲取預設的記憶體使用計算函式

MemorySizeCalculator calculator = new MemorySizeCalculator(context);  
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();  
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();  

2.)設定Glide磁碟快取大小

 File cacheDir = context.getExternalCacheDir();//指定的是資料的快取地址
 int diskCacheSize = 1024 * 1024 * 30;//最多可以快取多少位元組的資料
 //設定磁碟快取大小
 builder.setDiskCache(new DiskLruCacheFactory(cacheDir.getPath(), "glide", diskCacheSize));

 也可以通過如下兩種方式

  //存放在data/data/xxxx/cache/
  builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide", diskCacheSize));
  //存放在外接檔案瀏覽器
  builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "glide", diskCacheSize));

3.)設定圖片解碼格式

//設定圖片解碼格式
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);

預設格式RGB_565使用記憶體是ARGB_8888的一半,但是圖片質量就沒那麼高了,而且不支援透明度

4.)設定快取記憶體大小

 //設定BitmapPool快取記憶體大小
  builder.setBitmapPool(new LruBitmapPool(memoryCacheSize));

5.)設定一個用來檢索cache中沒有的Resource的ExecutorService

為了使縮圖請求正確工作,實現類必須把請求根據Priority優先順序排好序。

builder.setDiskCacheService(ExecutorService service);
builder.setResizeService(ExecutorService service);

使用ModelLoader自定義資料來源:

例如我們使用了七牛雲端儲存,要根據不同的要求請求不同尺寸不同質量的圖片,這時我們就可以使用自定義資料來源

  1.)定義處理URL介面

public interface IDataModel {

    String buildDataModelUrl(int width, int height);

}

2.)實現處理URL介面

JpgDataModel
public class JpgDataModel implements IDataModel {
    private String dataModelUrl;

    public JpgDataModel(String dataModelUrl) {
        this.dataModelUrl = dataModelUrl;
    }

    @Override
    public String buildDataModelUrl(int width, int height) {
        //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/jpg
        return String.format("%s?imageView2/1/w/%d/h/%d/format/jpg", dataModelUrl, width, height);
    }
}
WebpDataModel
public class WebpDataModel implements IDataModel {
    private String dataModelUrl;

    public WebpDataModel(String dataModelUrl) {
        this.dataModelUrl = dataModelUrl;
    }

    @Override
    public String buildDataModelUrl(int width, int height) {
        //http://78re52.com1.z0.glb.clouddn.com/resource/gogopher.jpg?imageView2/1/w/200/h/200/format/webp
        return String.format("%s?imageView2/1/w/%d/h/%d/format/webp", dataModelUrl, width, height);
    }
}

3.)實現ModelLoader

public class MyDataLoader extends BaseGlideUrlLoader<IDataModel> {
    public MyDataLoader(Context context) {
        super(context);
    }

    public MyDataLoader(ModelLoader<GlideUrl, InputStream> urlLoader) {
        super(urlLoader, null);
    }

    @Override
    protected String getUrl(IDataModel model, int width, int height) {
        return model.buildDataModelUrl(width, height);
    }

    /**
     */
    public static class Factory implements ModelLoaderFactory<IDataModel, InputStream> {

        @Override
        public ModelLoader<IDataModel, InputStream> build(Context context, GenericLoaderFactory factories) {
            return new MyDataLoader(factories.buildModelLoader(GlideUrl.class, InputStream.class));
        }

        @Override
        public void teardown() {
        }
    }
}

4.)根據不同的要求採用不同的策略載入圖片

   //載入jpg圖片
   Glide.with(this).using(new MyDataLoader(this)).load(new JpgDataModel(imageUrl)).into(imageView);
   //載入webp圖片
   Glide.with(this).using(new MyDataLoader(this)).load(new WebpDataModel(imageUrl)).into(imageView);

5.)如何跳過.using()

public class MyGlideModule implements GlideModule {
    ...
    @Override
    public void registerComponents(Context context, Glide glide) {
        glide.register(IDataModel.class, InputStream.class, 
            new MyUrlLoader.Factory());
    }
}

上面的實現跳過using()

   //載入jpg圖片
   Glide.with(this).load(new JpgDataModel(imageUrl)).into(imageView);
   //載入webp圖片
   Glide.with(this).load(new WebpDataModel(imageUrl)).into(imageView);

 使用signature()實現自定義cacheKey:

    Glide 以 url、viewwidth、viewheight、螢幕的解析度等做為聯合key,官方api中沒有提供刪除圖片快取的函式,官方提供了signature()方法,將一個附加的資料加入到快取key當中,多媒體儲存資料,可用MediaStoreSignature類作為識別符號,會將檔案的修改時間、mimeType等資訊作為cacheKey的一部分,通過改變key來實現圖片失效相當於軟刪除。

1.)使用StringSignature

Glide.with(this).load(yourFileDataModel).signature(new StringSignature("1.0.0")).into(imageView);

2.)使用MediaStoreSignature

Glide.with(this) .load(mediaStoreUri).signature(new MediaStoreSignature(mimeType, dateModified, orientation)).into(view);

3.)使用自定義Signature

public class IntegerVersionSignature implements Key {
  private int currentVersion;
  public IntegerVersionSignature(int currentVersion) {
     this.currentVersion = currentVersion;
  }
  @Override
  public boolean equals(Object o) {
    if (o instanceof IntegerVersionSignature) {
      IntegerVersionSignature other = (IntegerVersionSignature) o;
      return currentVersion = other.currentVersion;
    }
    return false;
  }
  @Override
  public int hashCode() {
    return currentVersion;
  }
  @Override
  public void updateDiskCacheKey(MessageDigest md) {
    messageDigest.update(ByteBuffer.allocate(Integer.SIZE)
.putInt(signature).array());
  }
}

小結:

     今天學了Glide的一些自定義擴充套件知識,接下來學習一下Glide與OKHttp的結合,已經簡單探析一下內部使用。

 

相關文章