Picasso,Glide坪蚁,F(xiàn)resco對比
上一篇我們分析了Picasso啃擦,這一篇我們來分析Glide源碼的調(diào)用流程馍惹,目前主流的圖片加載框架除了Picasso和Glide脯厨,還有Facebook開源的Fresco,有時間也將開一篇來分析。下面用一張表格來對3者進行對比,如下:
示例
Glide.with( activity )
.load( imageUrl )//指定加載路徑
.placeholder( R.mipmap.ic_launcher )//加載前默認圖
.error( R.mipmap.ic_launcher )//加載錯誤時顯示的圖片
.override( 300, 300 )//指定圖片大小
.centerCrop()//縮放叠聋,太大會裁剪并填滿整個控件
.fitCenter()//縮放,會顯示完整圖片受裹,但有可能不會填滿整個控件
.skipMemoryCache( true )//跳過內(nèi)緩存碌补,但仍會使用硬盤緩存
.diskCacheStrategy( DiskCacheStrategy.NONE )//不進行磁盤緩存
.diskCacheStrategy( DiskCacheStrategy.RESOURCE )//只緩存轉(zhuǎn)換過后的圖片
.diskCacheStrategy( DiskCacheStrategy.ALL )//既緩存原始圖片,也緩存轉(zhuǎn)換過后的圖片
.diskCacheStrategy( DiskCacheStrategy.DATA )//只緩存原始圖片
.diskCacheStrategy( DiskCacheStrategy.AUTOMATIC )//根據(jù)圖片資源自動選擇一種緩存策略(默認選項)
.priority( Priority.HIGH )//指定優(yōu)先級,但沒法保證一定按優(yōu)先級加載
.into( (ImageView) view );//顯示目標
如示例所示厦章,根據(jù)不同的需求場景镇匀,我們可以為Glide指定不同的配置。由于Glide源碼非常龐大和復(fù)雜闷袒,因此,本篇只分析3個主要的調(diào)用流程岩梳,即:
Glide.with( getApplicationContext() )
.load( imageUrl )
.into( (ImageView) view );
源碼分析
public class Glide implements ComponentCallbacks2 {
......
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
......
//獲取RequestManagerRetriever
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).");
//初始化Glide囊骤,并獲取RequestManagerRetriever
return Glide.get(context).getRequestManagerRetriever();
}
}
with根據(jù)不同的上下文參數(shù),提供了多個重載方法冀值,因為不同的上下文環(huán)境對圖片加載的生命周期也物,會有不同的影響。
with方法將返回一個RequestManager 列疗,而RequestManager 的獲取滑蚯,需要通過RequestManagerRetriever()這個檢索器來構(gòu)造,并且抵栈,一個上下文環(huán)境只持有一個檢索器告材。
假設(shè)第一次調(diào)用,在獲取RequestManagerRetriever檢索器前古劲,將先初始化Glide斥赋。如源碼中所示,Glide.get(context)將初始化并返回Glide對象产艾。
public class Glide implements ComponentCallbacks2 {
//獲取單例
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
//初始化檢查
checkAndInitializeGlide(context);
}
}
}
return glide;
}
//初始化檢查
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
//構(gòu)造一個new GlideBuilder()并調(diào)用雙參的重載方法
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
//初始化
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
......
//構(gòu)造Glide對象
Glide glide = builder.build(applicationContext);
......
//保存到靜態(tài)成員中
Glide.glide = glide;
}
.......
}
Glide通過雙重檢查鎖方式疤剑,來初始化和構(gòu)造單例對象。我們看到,在initializeGlide方法中new了一個GlideBuilder闷堡,它用來構(gòu)建Glide對象隘膘,并將對象保存到靜態(tài)成員變量glide 中。我們看build方法如何構(gòu)建杠览。
public final class GlideBuilder {
......
Glide build(@NonNull Context context) {
// 創(chuàng)建資源加載請求器弯菊,是一個線程池,用于加載源數(shù)據(jù)(URL等)
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
//查找磁盤緩存的線程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
//動畫執(zhí)行的線程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
// 內(nèi)存計算器
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
// 網(wǎng)絡(luò)狀態(tài)檢測器
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
//Bitmap復(fù)用池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
// 數(shù)組資源緩存池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
//用于緩存加載完成和顯示的圖片數(shù)據(jù)資源
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
// 磁盤緩存器踱阿,默認為 APP 內(nèi)部私密目錄
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 圖片加載引擎误续,用于執(zhí)行圖片加載請求驅(qū)動
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
// 構(gòu)建一個請求監(jiān)聽器列表
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//構(gòu)建RequestManager的檢索器
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
//構(gòu)建Glide
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
buid方法構(gòu)建了許多池子,同時生成上面RequestManager的檢索器扫茅,在最后構(gòu)建Glide時將所有參數(shù)傳入蹋嵌。 Glide 的構(gòu)造方法代碼量非常多,故省略大量代碼葫隙,只顯示核心邏輯栽烂。
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptionsFactory defaultRequestOptionsFactory,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
boolean isLoggingRequestOriginsEnabled,
boolean isImageDecoderEnabledForBitmaps,
int hardwareBitmapFdLimit) {
// 賦值
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;
final Resources resources = context.getResources();
// 新建注冊器
registry = new Registry();
registry.register(new DefaultImageHeaderParser());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
List<ImageHeaderParser> imageHeaderParsers = registry.getImageHeaderParsers();
// 創(chuàng)建解碼器
ByteBufferGifDecoder byteBufferGifDecoder =
new ByteBufferGifDecoder(context, imageHeaderParsers, bitmapPool, arrayPool);
ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder =
VideoDecoder.parcel(bitmapPool);
ResourceDecoder<ByteBuffer, Bitmap> byteBufferBitmapDecoder;
ResourceDecoder<InputStream, Bitmap> streamBitmapDecoder;
if (isImageDecoderEnabledForBitmaps && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
streamBitmapDecoder = new InputStreamBitmapImageDecoderResourceDecoder();
byteBufferBitmapDecoder = new ByteBufferBitmapImageDecoderResourceDecoder();
} else {
Downsampler downsampler =
new Downsampler(
registry.getImageHeaderParsers(),
resources.getDisplayMetrics(),
bitmapPool,
arrayPool);
byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
}
ResourceDrawableDecoder resourceDrawableDecoder = new ResourceDrawableDecoder(context);
// 創(chuàng)建數(shù)據(jù)轉(zhuǎn)換器
ResourceLoader.StreamFactory resourceLoaderStreamFactory =
new ResourceLoader.StreamFactory(resources);
ResourceLoader.UriFactory resourceLoaderUriFactory = new ResourceLoader.UriFactory(resources);
ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
new ResourceLoader.FileDescriptorFactory(resources);
ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory =
new ResourceLoader.AssetFileDescriptorFactory(resources);
BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);
// 創(chuàng)建轉(zhuǎn)碼器
BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();
ContentResolver contentResolver = context.getContentResolver();
// 注冊各個類型的解碼器和編碼器
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
......
.register(
Drawable.class,
byte[].class,
new DrawableBytesTranscoder(
bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
.register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
// 創(chuàng)建圖片顯示目標對象工廠
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
// 創(chuàng)建 GlideContext 對象,注意傳入的參數(shù)
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
}
構(gòu)造方法主要是初始化模型轉(zhuǎn)換器、解碼器腺办、轉(zhuǎn)碼器和編碼器焰手,并對各種類型在注冊表進行注冊。Glide的整個加載流程將經(jīng)歷:model(數(shù)據(jù)源)-->data(轉(zhuǎn)換數(shù)據(jù))-->decode(解碼)-->transformed(縮放)-->transcoded(轉(zhuǎn)碼)-->encoded(編碼保存到本地)怀喉,所以在構(gòu)造方法里初始化這些對象书妻,是為Gilde后續(xù)的加載流程做準備的。
回到一開始的width方法躬拢。在GlideBuilder 中躲履,已經(jīng)創(chuàng)建好了RequestManagerRetriever檢索器 ,RequestManagerRetriever 將通過get方法來獲取RequestManager聊闯。
public class RequestManagerRetriever implements Handler.Callback {
......
private volatile RequestManager applicationManager;
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
......
//Application上下文環(huán)境
private RequestManager getApplicationManager(@NonNull Context context) {
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
Glide glide = Glide.get(context.getApplicationContext());
//新建ApplicationLifecycle()和EmptyRequestManagerTreeNode
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
//獲取RequestManager
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
//在主線程中工猜,并且上下文不是Application
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
//對3種上下文進行判斷
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
//工廠接口
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
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);
}
};
}
在構(gòu)造RequestManagerRetriever時,倘若沒有設(shè)置RequestManagerFactory工廠菱蔬,那么將使用默認的匿名內(nèi)部類DEFAULT_FACTORY 來構(gòu)造RequestManager篷帅。
RequestManagerRetriever的get方法主要分2種情況,其中子線程和Application上下文環(huán)境最為簡單拴泌,它將使用Application為上下文魏身,構(gòu)建RequestManager,并且由源碼所示蚪腐,RequestManager也是一個單例叠骑,也就是說,一種上下文只有一個RequestManagerRetriever檢索器削茁,也只有一個RequestManager對象宙枷。
而其他上下文情況,最終都會以Activity為上下文茧跋,調(diào)用參數(shù)為Activity的get方法慰丛,我們繼續(xù)分析,看以Activity為上下文的調(diào)用過程和以Application為上下文的情況有什么不同瘾杭。
public class RequestManagerRetriever implements Handler.Callback {
//Tag緩存
static final String FRAGMENT_TAG = "com.bumptech.glide.manager";
//map緩存
final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
new HashMap<>();
......
public RequestManager get(@NonNull Activity activity) {
//后臺線程
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(
activity, fm, null, isActivityVisible(activity));
}
}
//activity是否退出了
private static boolean isActivityVisible(Activity activity) {
return !activity.isFinishing();
}
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//獲取一個空fragment
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//獲取RequestManager
RequestManager requestManager = current.getRequestManager();
//為空則構(gòu)建
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//通過名為FRAGMENT_TAG的Tag獲取
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//空則從緩存中獲取
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
//緩存空則新建
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
//Activity沒退出
if (isParentVisible) {
//開啟生命周期監(jiān)聽
current.getGlideLifecycle().onStart();
}
//緩存起來
pendingRequestManagerFragments.put(fm, current);
//加到當前Activity
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//發(fā)送ID_REMOVE_FRAGMENT_MANAGER消息清除緩存
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
//消息回調(diào)移除緩存RequestManagerFragment
@Override
public boolean handleMessage(Message message) {
boolean handled = true;
Object removed = null;
Object key = null;
switch (message.what) {
case ID_REMOVE_FRAGMENT_MANAGER:
android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
key = fm;
//從緩存移除
removed = pendingRequestManagerFragments.remove(fm);
break;
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
break;
}
if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
}
return handled;
}
}
RequestManagerFragment 是一個空的Fragment诅病,Glide正是通過它來監(jiān)聽Activity的生命周期,換句話說粥烁,當Activity的生命周期方法被回調(diào)贤笆,也就同時回調(diào)了Fragment(RequestManagerFragment )。
如源碼中所示讨阻,如果RequestManagerFragment被添加到當前的Activity中芥永,那么通過變量名FRAGMENT_TAG就可以獲取到,那為什么還需要使用pendingSupportRequestManagerFragments這個Map來進行緩存钝吮,而添加到Activity后埋涧,又立即通過消息將其從Map中移除板辽?
因為并發(fā)。以下面的代碼為例:
Glide.with(activity).load(url1).into(imageView1); //request1
Glide.with(activity).load(url2).into(imageView2); //request2
Fragment添加是通過Handler消息隊列操作的棘催,而消息隊列執(zhí)行在主線程之后劲弦。假設(shè)request1創(chuàng)建RequestManagerFragment,并提交了事務(wù)醇坝,在RequestManagerFragment添加消息未執(zhí)行邑跪,也就是說RequestManagerFragment未被添加到Acitivy中前,request2執(zhí)行到fm.findFragmentByTag(FRAGMENT_TAG)呼猪,current 將會為null画畅,那么,如果不使用map來緩存郑叠,RequestManagerFragment又將實例化一個夜赵,也就意味著明棍,當前Activity將出現(xiàn)重復(fù)添加RequestManagerFragment的情況乡革。
由于移除消息在提交事務(wù)消息之后,等到移除消息執(zhí)行時摊腋,后面的請求已經(jīng)能通過FRAGMENT_TAG獲取到RequestManagerFragment了沸版,Map沒有必要再繼續(xù)緩存著,因此兴蒸,從緩存移除视粮,以避免內(nèi)存泄漏和減少內(nèi)存壓力。
下面來看RequestManagerFragment是監(jiān)聽Activity生命周期做了哪些操作橙凳。
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
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();
}
}
RequestManagerFragment 構(gòu)造時構(gòu)建了一個ActivityFragmentLifecycle 對象蕾殴,它正是負責(zé)生命周期的回調(diào)。
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@Override
public void addListener(@NonNull LifecycleListener listener) {
lifecycleListeners.add(listener);
if (isDestroyed) {
listener.onDestroy();
} else if (isStarted) {
listener.onStart();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
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();
}
}
}
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
ActivityFragmentLifecycle 實現(xiàn)了Lifecycle 接口岛啸,通過addListener方法將LifecycleListener添加到集合中钓觉,當Activity生命周期被回調(diào),將觸發(fā)RequestManagerFragment對應(yīng)的生命周期坚踩,也將觸發(fā)ActivityFragmentLifecycle 遍歷lifecycleListeners集合荡灾,回調(diào)每個LifecycleListener對應(yīng)的方法。
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
LifecycleListener接口定義了3個生命周期回調(diào)瞬铸,它的LifecycleListener的實現(xiàn)類有許多個批幌,其中就包括RequestManager類。
with方法分析完畢嗓节,總結(jié)一下它所做的工作:
- 構(gòu)造并初始化Gilde對象荧缘;
- 在構(gòu)建Gilde對象的過程中,構(gòu)建RequestManagerRetriever檢索器拦宣;
- 檢索器在上下文環(huán)境不是Application的情況下胜宇,會構(gòu)建一個RequestManagerFragment 來監(jiān)聽頁面的生命周期耀怜。
- 構(gòu)建RequestManager對象。Application環(huán)境下桐愉,RequestManagerRetriever持有RequestManager财破,非Application環(huán)境下,RequestManagerFragment持有RequestManager从诲。