決策模式: DiskCacheStrategy of Glide
Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
這次要從 Glide 的硬體快取決策去看決策模式的應用。
決策模式提供了當情況的變化在於算法細節時,我們可以進行的封裝方式。
下面是抽象類別 DiskCacheStrategy 的介面
跟他提供了五種不同的決策 (為了方便閱讀我把實作細節都拿掉了)
- ALL : 全部圖像包含尺寸變換都儲存快取
- NONE : 不作儲存快取
- DATA : 在解碼前儲存(只存遠端資料)
- RESOURCE : 在解碼後儲存 (包含本地端跟遠端)
- AUTOMATIC : 自動判斷是否該儲存快取 (預設值)
下面的五種決策類宣告成 static final,讓編譯器在編譯時會創建他們的實體,
在整個使用上變得更加容 易。
public abstract class DiskCacheStrategy { public static final DiskCacheStrategy ALL = new DiskCacheStrategy() { public boolean isDataCacheable(DataSource dataSource) {} public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,EncodeStrategy encodeStrategy) {} public boolean decodeCachedResource() {} public boolean decodeCachedData() {} }; public static final DiskCacheStrategy NONE = new DiskCacheStrategy() { public boolean isDataCacheable(DataSource dataSource) {} public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,EncodeStrategy encodeStrategy) {} public boolean decodeCachedResource() {} public boolean decodeCachedData() {} }; public static final DiskCacheStrategy DATA = new DiskCacheStrategy() { public boolean isDataCacheable(DataSource dataSource) {} public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,EncodeStrategy encodeStrategy) {} public boolean decodeCachedResource() {} public boolean decodeCachedData() {} }; public static final DiskCacheStrategy RESOURCE = new DiskCacheStrategy() { public boolean isDataCacheable(DataSource dataSource) {} public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,EncodeStrategy encodeStrategy) {} public boolean decodeCachedResource() {} public boolean decodeCachedData() {} }; public static final DiskCacheStrategy AUTOMATIC = new DiskCacheStrategy() { public boolean isDataCacheable(DataSource dataSource) {} public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,EncodeStrategy encodeStrategy) {} public boolean decodeCachedResource() {} public boolean decodeCachedData() {} };
// the interface
public abstract boolean isDataCacheable(DataSource dataSource); public abstract boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource, EncodeStrategy encodeStrategy); public abstract boolean decodeCachedResource(); public abstract boolean decodeCachedData(); }
藉由封裝進 RequestOptions 讓使用者可以自由改變想要的策略
在資源解碼時使用
下方是類 DecodeJob 部分源碼
// Decide the stage private Stage getNextStage(Stage current) { switch (current) { case INITIALIZE: return diskCacheStrategy.decodeCachedResource() ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE); case RESOURCE_CACHE: return diskCacheStrategy.decodeCachedData() ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE); case DATA_CACHE: // Skip loading from source if the user opted to only retrieve the resource from cache. return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; case SOURCE: case FINISHED: return Stage.FINISHED; default: throw new IllegalArgumentException("Unrecognized stage: " + current); } } @Synthetic @NonNull Resource onResourceDecoded(DataSource dataSource, @NonNull Resource decoded) { ... Resource result = transformed; boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey); if (diskCacheStrategy.isResourceCacheable(isFromAlternateCacheKey, dataSource, encodeStrategy)) { ... } LockedResource lockedResult = LockedResource.obtain(transformed); deferredEncodeManager.init(key, encoder, lockedResult); result = lockedResult; } return result; }
簡易架構圖
Glide.with(context) .load(imageUrl) .apply(RequestOptions() .diskCacheStrategy(DiskCacheStrategy.RESOURCE)) .into(imageView)
基本使用 Glide 流程圖(Create)
針對創建 Target 部分的流程圖(Start)
更加詳細版
*下方類別圖只畫了部分相關的類別
留言
張貼留言