我以爲使用第三方的庫時,要作到 知其然 知其因此然 欲然革之 棄之天然 好吧不裝x了說人話就是,對一個庫的瞭解程度能夠化爲爲這樣幾個等級:緩存
總體Glide是怎樣架構的,大輪子如何轉動起來,經過這篇文章對Glide的總體有個認識而後逐一突破。 (這圖畫我了倆小時....,手動比心,求贊) bash
Glide的簡單使用是下面這樣的:網絡
Glide.with(context).load("http:xxxx").into(target)
複製代碼
先看看Glide.with()方法作了什麼。Glide的with(x)方法的參數能夠是:Context、Activity、Fragment、View。 不管是哪一種參數都會直接或者間接的調用下面這個方法:架構
private static RequestManagerRetriever getRetriever(@Nullable Context context){
Preconditions.checkNotNull(context,"..");
return Glide.get(context).getRequestManagerRetriever();
}
複製代碼
這個方法最終會返回一個RequestManagerRetriever對象。Glide.get(ctx)返回的是一個Glide對象,內部使用的單例模式,進程內Glide是單例,以下。敲黑板,這不就是傳說中的雙重效驗鎖。app
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
複製代碼
找到了Glide建立的地方,Glide.get(ctx)->checkAndInitializeGlide(ctx)->initializeGlide(ctx,glideBuilder),最終建立glide單例對象的重擔落在了initializeGlide(..)方法上ide
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
GeneratedAppGlideModule annotationGeneratedModulegetAnnotationGeneratedGlideModules();
....
Glide glide = builder.build(applicationContext);
...
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
複製代碼
咱們源碼中關於使用APT技術動態加載GeneratedAppGlideModule對象而後配置Glide相關代碼隱去了,篇幅有限這一部分單獨成篇詳細探究。ui
先看這個方法主要完成了三件事:this
# GlideBuild
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {...}
if (diskCacheExecutor == null) {...}
if (animationExecutor == null) {...}
...
if (memoryCache == null) {...}
if (diskCacheFactory == null) {...}
if (engine == null) {...}
return new Glide(context, engine,memoryCache,bitmapPool,arrayPool...)
}
複製代碼
如上圖通過層層最終調用initializeGlide(),這個方法中使用GlideBuilder對象夠建出Glide對象,值得關注的是他是一個單例。並且當在GlideBuider沒有設置響應參數的時候會生成默認的參數供GlideBuilder建立出Glide對象。spa
書接上回,咱們已經對Glide這個類的建立有了一個大致的認知。操作系統
仍是那行代碼,
RequestManager requestManager = Glide.with(this);
複製代碼
這行代碼順序的作了三件事
RequestManagerReriever類的註釋
A collection of static methods for creating new RequestManagers or retrieving existing ones from activities and fragment.
這個類的職責就是建立新的RequestManager或者在activity和fragment中檢索出已經存在的。
建立一個RequestManager的資料中很重要的一個就是LifeCycle
摘了比較核心的一段代碼標記,加了註釋。
private RequestManager fragmentGet(@NonNull Context context,FragmentManager fm,Fragment parentHint,boolean isParentVisible) {
//獲取一個RequestManagerFragment
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//試圖在RequestManagerFragment中獲取requestManager
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
//若是爲空就建立一個而且存到RequestManagerFragment中
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
複製代碼
注意的點
總結下RequestManagerReriever對象建立RequestManager流程。
RequestManager見名知意,管理圖片請求,啓動、暫停、從新啓動請求,依據所在組件的生命週期週期和網絡作出恰當的動做
使用RequestManager對象一系列的load()方法最終可以獲得一個RequestBuilder的對象, RequestBuilder是一個泛型類,加載什麼樣的類型圖片資源決定了他是什麼類型,圖片資源的來源多是Recource、File、或者網絡。
RequestBuilder<T> requestBuidlder = requestManager.load(xxxx);
複製代碼
獲得RequestBuilder以後,就能夠對請求的圖片資源作一些指望設置
RequestBuildler,均可以經過RequestOptions進行配置。ReuqestBuilder繼承了BaseRequestOptions類,BaseRequestOption這個類是鏈接RequestOption和RequestBuilder的橋樑,經過這個類的對象對RequestOption進行一系列的設置。
Request有三個實現類,RequestCoordinator,SingleRequest和ErrorRequestCoordinator,RequestCoodinator。
#RequestBuilder 構建ErrorRequestCoordinator對象的方法爲例。
private Request buildRequestRecursive(..) {
//構建請求控制
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
//構建的主請求
Request mainRequest =(...);
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
//構建錯誤請求
Request errorRequest =
errorBuilder.buildRequestRecursive(..);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
複製代碼
整個Request構建管理的構成以下
這只是一個總體的流程,關於更詳細的Request管理,包括若是感知聲明週期的,重複請求如何管理,參數設置的原理等等單獨成篇分析。Request對象的begin()方法根據圖片不一樣的來源去加載,獲取到指望尺寸以後就會調用onSizeReady(),傳入一系列參數信息。
onSizeReady(){
...
loadStatus =
engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
...
}
複製代碼
engin.load()
public synchronized <R> LoadStatus load(...) {
...
EngineJob<R> engineJob =engineJobFactory.build(...);
DecodeJob<R> decodeJob =decodeJobFactory.build(...);
...
engineJob.addCallback(cb, callbackExecutor);//加載
engineJob.start(decodeJob);//解碼,對二進制數據轉換成圖片根據配置進行編輯
...
return new LoadStatus(cb, engineJob);
}
複製代碼
EngineJob.load實際加載圖片數據的執行者,加載完以後交給decodeJob處理。內部具體如何實現的單獨成篇分析,如這部分中線程池如何使用,Bitmap的使用技巧等。
以上對Glide這個優秀的開源庫有了一個總體的認識,大致分爲三個部分