上一節(jié)我們簡單的介紹了Glide的常規(guī)使用方法若锁,有需要的話可以看看上一節(jié):
Glide.with(this).load(url).into(imageView)
標題這一句代碼赞季,囊括了整個Glide的核心功能,可以說Glide在這一行代碼中做了成噸的工作,最繁重的任務是在into方法中略贮,但是我們根據(jù)順序掉房,首先看一下with方法。說到Glide源碼颤芬,面試中大家可能都知道Glide為何能監(jiān)聽頁面或者application的生命周期悲幅,從而及時的取消請求和回收對象套鹅,是通過綁定一個空的fragment。那么我們就來看一下汰具,with方法中卓鹿,是如何實現(xiàn)這個操作的。
Glide.with(this)方法
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/** @deprecated */
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
glide提供的with方法比較多留荔,其實這里看的出來吟孙,不管是傳入context還是activity亦或是fragment,其實還是拿到當前頁面所屬的context聚蝶,那么這里是情況其實只有兩種杰妓,一種是普通的context,另一種這是applicationcontext碘勉。我們以傳入context為例巷挥,調(diào)用的是return getRetriever(context).get(context),返回值則是一個RequestManager验靡,我們跟進去看看getRetriever(context)方法:
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
Preconditions.checkNotNull(context, "You cannot start a load on a not yet attached View or a Fragment
where getActivity() returns null (which usually occurs when getActivity() is called
before the Fragment is attached or after the Fragment is destroyed).");
return get(context).getRequestManagerRetriever();
}
checkNotNull方法執(zhí)行的是context的空檢查倍宾,我們繼續(xù)看一下get(context).getRequestManagerRetriever()中的get(context)
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
Class var1 = Glide.class;
synchronized(Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
這里get方法是獲取glide實例,實現(xiàn)的一個單例方法胜嗓,其中checkAndInitializeGlide對glide進行初始化高职,這里我們不去細究回到上一步繼續(xù)看看get(context).getRequestManagerRetriever()的getRequestManagerRetriever()方法
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return this.requestManagerRetriever;
}
這里直接返回的是RequestManagerRetriever,那么這個變量是什么時候初始化的呢兼蕊,我們看下Glide的build方法發(fā)現(xiàn)這里初始化了RequestManagerRetriever初厚。到這里with方法中的getRetriever(context).get(context)的getRetriever結(jié)束,我們繼續(xù)看看get(context)孙技,這里應該返回了一個RequestManagerRetriever里面的RequestManager产禾,來看下源碼:
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else {
if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return this.get((FragmentActivity)context);
}
if (context instanceof Activity) {
return this.get((Activity)context);
}
if (context instanceof ContextWrapper) {
return this.get(((ContextWrapper)context).getBaseContext());
}
}
return this.getApplicationManager(context);
}
}
這里看出將context分成了兩種類型,一種是context instanceof Application牵啦,另一種則是普通context亚情。先看看如果是普通的context,這里FragmentActivity哈雏、Activity其實差不多楞件,內(nèi)部創(chuàng)建的fragment支持的類型不同。如果是ContextWrapper類型則繼續(xù)取到baseContext裳瘪,遞歸調(diào)用get(context)土浸。那么這里我們看看Activity的場景的源碼this.get((Activity)context):
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return this.get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getFragmentManager();
return this.fragmentGet(activity, fm, (android.app.Fragment)null, isActivityVisible(activity));
}
}
這里的if判斷表示如果當前程序是在后臺運行,那么傳入getApplicationContext去get RequestManager 彭羹,這里ApplicationContext的情況我們等會兒單獨再講黄伊,繼續(xù)看下面的代碼,我們看到activity.getFragmentManager()派殷,獲取當前activity的FragmentManager还最,然后調(diào)用了fragmentGet方法墓阀,那么繼續(xù)看看這個方法的源碼:
/** @deprecated */
@Deprecated
@NonNull
private RequestManager fragmentGet(@NonNull Context context, @NonNull FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) {
RequestManagerFragment current = this.getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
重點來了,我們看到第一行返回了一個RequestManagerFragment 拓轻,我們跟進去看看這個fragment是怎么創(chuàng)建的:
@NonNull
private RequestManagerFragment getRequestManagerFragment(@NonNull FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment)fm.findFragmentByTag("com.bumptech.glide.manager");
if (current == null) {
current = (RequestManagerFragment)this.pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
this.pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();
this.handler.obtainMessage(1, fm).sendToTarget();
}
}
return current;
}
這里我們先通過pendingRequestManagerFragments從緩存中去拿RequestManagerFragment 斯撮,這里的pendingRequestManagerFragment就是一個hashmap,Map<FragmentManager, RequestManagerFragment>扶叉,如果緩存中沒有勿锅,那么去new一個fragment并且將其添加到緩存中,重點來了枣氧, fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();這里便將一個沒有ui的fragment添加到了context對應的activity上粱甫。回到前面我們提到的applicationcontext作瞄,看看這種情況茶宵,調(diào)用的是getApplicationManager:
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
if (this.applicationManager == null) {
synchronized(this) {
if (this.applicationManager == null) {
Glide glide = Glide.get(context.getApplicationContext());
this.applicationManager = this.factory.build(glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context.getApplicationContext());
}
}
}
return this.applicationManager;
}
這里我們直接看factory的build方法,跟進去看一源碼:
private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
這里根據(jù)傳入applicationContext去創(chuàng)建一個RequestManager并返回宗挥,到這里整個with方法就結(jié)束了乌庶,我們再看看fragment對應的生命周期方法中做了什么:
@Override
public void onDetach() {
super.onDetach();
unregisterFragmentWithRoot();
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
unregisterFragmentWithRoot();
}
這里可以看出,當activity觸發(fā)生命周期的時候契耿,當前無UI的fragment也會觸發(fā)相應的生命周期方法瞒大,那么這里的lifecycle調(diào)用到了哪里呢,跟進去發(fā)現(xiàn)調(diào)用的是ActivityFragmentLifecycle實現(xiàn)的幾個方法:
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onDestroy();
}
}
這里的lifecycleListeners存儲了前面添加的多個生命周期的監(jiān)聽搪桂,在這里全部觸發(fā)透敌,那么這里我們之前添加的
lifecycleListener 包括了RequestManager中的,我們在RequestManager創(chuàng)建的時候就已經(jīng)添加了一個listener到lifecycleListeners中踢械,所以這里的onStart酗电、onStop、onDestroy會調(diào)用RequestManager里面的對應方法内列,RequestManager作為一個管理類撵术,管理了兩個重要的對象,一個是target话瞧,另一個是request嫩与,因此RequestManager通過監(jiān)聽生命周期方法,同時控制了target和request的加載情況交排,我們來看下代碼:
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
可以看到划滋,在對應的生命周期方法中控制了targetTracker和requestTracker,這兩個對象則分別控制這target和request的生命周期埃篓。到這里我們的width方法源碼流程就結(jié)束了处坪。
RequestManager的load(url)方法
上面我們分析的是Glide.with(this).load(url).into(imageView)中的with方法,那么我們繼續(xù)看load,width返回的是RequestManager稻薇,那么自然load方法在RequestManager中,我們看下源碼:
@Override
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
@Override
public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
return asDrawable().load(drawable);
}
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
@Override
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
@Override
public RequestBuilder<Drawable> load(@Nullable File file) {
return asDrawable().load(file);
}
@Override
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return asDrawable().load(resourceId);
}
@Override
public RequestBuilder<Drawable> load(@Nullable URL url) {
return asDrawable().load(url);
}
@Override
public RequestBuilder<Drawable> load(@Nullable byte[] model) {
return asDrawable().load(model);
}
@Override
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
glide提供的load方法極多胶征,涵蓋了大多數(shù)的圖片加載資源塞椎,例如字節(jié)碼,URL睛低,Drawable案狠,文件,bitmap钱雷,字符串的圖片地址等等骂铁,這里我們就以常用的字符串的圖片地址為例看下代碼:
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
@NonNull
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
@Override
@CheckResult
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
我們先看asDrawable方法,其實就是設置了圖片資源的類型罩抗,然后創(chuàng)建了一個RequestBuilder對象拉庵,然后傳入一個String類型并且調(diào)用load方法,這里是將我們的String URL設置到了model 對象中套蒂,并沒有開始請求钞支,所以我們的重點任務就放在了into方法中,它包括了獲取內(nèi)存緩存操刀,獲取磁盤緩存烁挟,請求,寫入內(nèi)存和磁盤緩存等許多操作骨坑,那么我們下一節(jié)再繼續(xù)分析最重要的一步into方法吧~
總結(jié)
首先通過width方法中的getRetriever方法撼嗓,完成Glide的初始化并且獲取到RequestManagerRetriever,RequestManagerRetriever主要用于管理和生成RequestManager欢唾,然后通過RequestManagerRetriever的get方法為activity創(chuàng)建一個無UI的fragment且警,并且綁定到當前activity,然后生成一個RequestManager并且與之關(guān)聯(lián)生命周期礁遣,當activity的生命周期發(fā)生改變時振湾,通知綁定的fragment,繼而通知到RequestManager的監(jiān)聽方法亡脸,從而控制對target和request的加載押搪、暫停和銷毀。
下一節(jié)我們講講into(imageview)中的內(nèi)存緩存: