
Glide介紹
Glide是一個(gè)快速高效的Android圖片加載庫,注重于平滑的滾動。Glide提供了易用的API,高性能、可擴(kuò)展的圖片解碼管道(decode pipeline),以及自動的資源池技術(shù)。Glide 支持拉取,解碼和展示視頻快照,圖片,和GIF動畫。Glide的Api是如此的靈活,開發(fā)者甚至可以插入和替換成自己喜愛的任何網(wǎng)絡(luò)棧。默認(rèn)情況下,Glide使用的是一個(gè)定制化的基于HttpUrlConnection的棧,但同時(shí)也提供了與Google Volley和Square OkHttp快速集成的工具庫。
雖然Glide 的主要目標(biāo)是讓任何形式的圖片列表的滾動盡可能地變得更快、更平滑,但實(shí)際上,Glide幾乎能滿足你對遠(yuǎn)程圖片的拉取/縮放/顯示的一切需求。
Glide的使用
本文是從4.10.0開始介紹的
- 最小SDK版本需要使用API 14(或者更高版本)
- Complie SDK Version需要使用API 27(或者更高版本)
- Glide使用的SupportLibrary 版本是27,如果需要不同的SupportLibrary版本可以用exclude將Glide的SupportLibrary從依賴中去掉,具體的在集成時(shí)說明
Glide導(dǎo)包
implementation('com.github.bumptech.glide:glide:4.10.0')
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
//如果使用了在Kotlin中使用了Glide注解,需要引入kapt依賴代替annotationProcessor依賴
//kapt 'com.github.bumptech.glide:compiler:4.10.0'
//若使用了不是27的SupportLibrary版本,使用以下代碼
implementation('com.github.bumptech.glide:glide:4.10.0') {
exclude group: "com.android.support"
}
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
Glide的基本用法
String url = "http://img1.dzwww.com:8080/tupian_pl/20150813/16/7858995348613407436.jpg";
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Glide.with(context)
.load(url)
.into(imageView);
- with(Context context) - 需要上下文,這里還可以使用 Activity、FragmentActivity、android.support.v4.app.Fragment、android.app.Fragment 的對象。將 Activity/Fragment 對象作為參數(shù)的好處是,圖片的加載會和 Activity/Fragment 的生命周期保持一致,例如:onPaused 時(shí)暫停加載,onResume 時(shí)又會自動重新加載。所以在傳參的時(shí)候建議使用 Activity/Fragment 對象,而不是 Context。
- load(String url) - 這里我們所使用的一個(gè)字符串形式的網(wǎng)絡(luò)圖片的 URL,后面會講解 load() 的更多使用方式
- into(ImageView imageView) - 你需要顯示圖片的目標(biāo) ImageView
String url = "http://img1.dzwww.com:8080/tupian_pl/20150813/16/7858995348613407436.jpg";
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Glide.with(context)
.load(url)
.thumbnail( 0.2f )
.placeholder(R.drawable.place_image)//圖片加載出來前,顯示的圖片
.error(R.drawable.error_image)//圖片加載失敗后,顯示的圖片
.into(imageView);
- placeholder(int resId) 圖片加載出來前顯示的預(yù)顯示圖片
- error(int resId) 加載失敗后顯示的預(yù)存圖片
上面這兩個(gè)參數(shù)也支持Drawable 參數(shù) - thumbnail 是做略圖的屬性,上面的例子中,如果是0.2f,則將會顯示原始圖片的20%的大小,如果原圖是 1000x1000 的尺寸,那么縮略圖將會是 200x200 的尺寸
縮略圖還有另外一種
private void loadImageThumbnailRequest(){
// setup Glide request without the into() method
DrawableRequestBuilder<String> thumbnailRequest = Glide.with( context ).load( url );
// pass the request as a a parameter to the thumbnail request
Glide.with( context )
.load( url )
.thumbnail( thumbnailRequest )
.into( imageView );
}
與上面第一種方式不同的是,這里的第一個(gè)縮略圖請求是完全獨(dú)立于第二個(gè)原始請求的。該縮略圖可以是不同的資源圖片,同時(shí)也可以對縮略圖做不同的轉(zhuǎn)換,等等...
圖片的大小調(diào)整
可以調(diào)用override來調(diào)整圖片的大小
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio
.into(imageViewResize);
transformation(變換)
Glide提供了transformation得功能,在獲取到請求的圖片之后,能對圖片進(jìn)行一些處理,例如:裁剪、模糊等;而transformation的強(qiáng)大在于可以自定義,這樣一來transformation不僅能處理bitmap,同樣可以用于處理GIF動畫,還有自定義資源類型。
Glide在API上提供的了5個(gè)相關(guān)的方法可以直接使用
circleCrop()//加載原形圖片
centerCrop()//方法是將圖片按比例縮放到足矣填充
centerInside()//保留圖片原本的長寬比,如果圖片長和寬(X和Y)均小于ImageView的長和寬,則不進(jìn)行放大,直接將圖片在ImageView中居中展示;否則對圖片的長和寬(X和Y)進(jìn)行等比例縮小,直到圖片至少一邊與ImageView重合,并且圖片完全顯示在ImageView里面,最終將圖片在ImageView中居中展示。
fitCenter()//保留圖片原本的長寬比,對圖片的長和寬(X和Y)進(jìn)行等比例縮放,直到圖片至少一邊與ImageView重合,并且圖片完全顯示在ImageView里面,最終將圖片在ImageView中居中展示
optionalFitCenter()//
使用方法如下
GlideApp.with(this)
.load(url)
.centerCrop()
.into(imageView);
可以直接調(diào)用以上方法,如果沒有直接可以調(diào)用的方法,需要通過RequestOptions來設(shè)置
RequestOptions options = new RequestOptions().centerCrop();
Glide.with(this)
.load(url)
.apply(options)
.into(imageView);
//靜態(tài)方法
Glide.with(this)
.load(url)
.apply(RequestOptions.centerCropTransform())
.into(imageView);
針對ImageView可能自身也會設(shè)置scaleType的情況,Glide在部分情況會自動應(yīng)用 FitCenter或CenterCrop,如果 scaleType 是 CENTER_CROP , Glide 將會自動應(yīng)用 CenterCrop 變換。如果 scaleType 為 FIT_CENTER 或 CENTER_INSIDE ,Glide會自動使用 FitCenter 變換
圖片的緩存處理
為了更快的加載圖片,我們肯定希望可以直接拿到圖片,而不是進(jìn)行網(wǎng)絡(luò)請求,所以我們需要緩存。Glide 通過使用默認(rèn)的內(nèi)存和磁盤緩存來避免不必要的網(wǎng)絡(luò)請求,之后我們再詳細(xì)的去看它的實(shí)現(xiàn)。
內(nèi)存緩存是 Glide 默認(rèn)幫我們做了的,除非你不需要,可以調(diào)用 skipMemoryCache(true) 告訴 Glide 跳過內(nèi)存緩存。這樣 Glide 就不會把這張圖片放到內(nèi)存緩存中,該方法只影響內(nèi)存緩存。
此外也可以調(diào)用用diskCacheStrategy方法自定義緩存策略
- DiskCacheStrategy.NONE 什么都不緩存
- DiskCacheStrategy.SOURCE 只緩存全尺寸圖
- DiskCacheStrategy.RESULT 只緩存最終的加載圖
- DiskCacheStrategy.ALL 緩存所有版本圖(默認(rèn)行為)
Glide.with(context)
.load(url)
.skipMemoryCache(true)
.diskCacheStrategy( DiskCacheStrategy.NONE )
.into(imageView);
圖片的優(yōu)先級
同一時(shí)間加載多個(gè)圖片,App 將難以避免這種情況。如果這個(gè)時(shí)候我們希望用戶的體驗(yàn)更好,往往會選擇先加載對于用戶更加重要的圖片。Glide 可以調(diào)用 .priority() 方法配合 Priority 枚舉來設(shè)置圖片加載的優(yōu)先級。
- Priority.LOW
- Priority.NORMAL
- Priority.HIGH
- Priority.IMMEDIAT
Glide.with( context )
.load( highPriorityImageUrl )
.priority (Priority.HIGH )
.into( imageView );
圖片的動畫效果
無論你是否使用占位圖,對于UI來說,圖片的改變是相當(dāng)大的一個(gè)動作。一個(gè)簡單的方法可以讓這個(gè)變化更平滑,更讓人眼接受,這就是使用crossfade動畫。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded
.crossFade(300)
.into(imageViewFade);
crossFade()方法可以攜帶參數(shù),參數(shù)代表著圖片的平滑替換時(shí)間,默認(rèn)是300毫秒
如果你想直接跳過這個(gè)動畫則直接調(diào)用.dontAnimate()方法
在圖片中
Glide gif和視頻的播放
許多圖片加載庫能處理好圖片的加載與顯示,但很多并不支持Gif。如果你的app需要支持Gif,Glide的簡單會讓體驗(yàn)更驚艷。如果你想要播放Gif,你只要使用之前處理圖片的類似的方法,
Glide
.with(context)
.load(gifUrl)
.asGif()
.error( R.drawable.full_cake)
.into( imageViewGif );
在上面的代碼中還有一個(gè)asGif的方法,這個(gè)方法是為了防止出入的gif圖片如果不是gif只是一個(gè)普通的圖片,會將它通過asGif方法裝換成gif,防止上面的方法調(diào)用后報(bào)錯(cuò)。如果你的app需要顯示一組網(wǎng)絡(luò)URL,可能包括普通的圖片或者Gif。在一些情況下,你可能并不在意是否要播放完整的Gif。如果你只是想要顯示Gif的第一幀,當(dāng)URl指向的的確是Gif,你可以調(diào)用asBitmap()將其作為常規(guī)圖片顯示。
此外glide還能夠播放視頻,不過只能播放本地視頻
String filePath = "/storrage/emulated/0/Pictures/video.mp4";
Glide.with( context )
.load( Uri.fromFile( new File( filePath ) ) )
.into( imageView );
Target
我們所涉及到的代碼都是直接加載圖片到 ImageView 中。Glide 隱藏做了所有的網(wǎng)絡(luò)請求和后臺的線程處理,圖片準(zhǔn)備好之后切回到 UI 線程刷新 ImageView。也就是說 ImageView 在我們代碼的鏈?zhǔn)浇Y(jié)構(gòu)中成為了最后一步,但是如果我們需要獲取到 Bitmap 本身
的話我們就需要用到 Target 了。Target 其實(shí)就是整個(gè)圖片的加載的生命周期,所以我們就可以通過它在圖片加載完成之后獲取到 Bitmap。其實(shí)對于 Target 可以簡單的理解為回調(diào),本身就是一個(gè) interface,Glide本身也為我們提供了很多 Target
private SimpleTarget<Bitmap> mSimpleTarget = new SimpleTarget<Bitmap>(500,500) {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> animation) {
mImageView.setImageBitmap(resource);
}
};
private void loadImageSimpleTarget() {
Glide.with( thi s)
.load( mUrl )
.asBitmap()
.into( mSimpleTarget );
}
首先創(chuàng)建了一個(gè) SimpleTarget 的對象并且實(shí)現(xiàn)了 onResourceReady() 方法,看方法名能知道是圖片加載完之后會調(diào)用該方法,參數(shù)就有我們需要的 Bitmap 。而使用 SimpleTarget 的對象的時(shí)候就像使用 ImageView 一樣,作為參數(shù)傳給 into() 方法就行了,Glide 會內(nèi)部去處理并返回結(jié)果給任何一個(gè)對象。這里我們?yōu)榱朔乐辜虞d Gif 、 Video 或者一些位置資源時(shí)與 mSimpleTarget 沖突,所以我們調(diào)用了 asBitmap() 方法,使其只能返回 Bitmap 對象。
當(dāng)我們使用 Custom View 時(shí),Glide 并不支持加載圖片到自定義 view 中的,使用 ViewTarget 更容易實(shí)現(xiàn)。
public void loadImageTarget(Context context){
CustomView mCustomView = (CustomView) findViewById(R.id.custom_view);
ViewTarget viewTarget = new ViewTarget<CustomView,GlideDrawable>( mCustomView ) {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
this.view.setImage(resource);
}
};
Glide.with(context)
.load(mUrl)
.into(viewTarget);
}
在 target 的 onResourceReady 回調(diào)方法中使用自定義 view 自己的方法去設(shè)置圖片,可以看到在創(chuàng)建 ViewTarget 的時(shí)候傳入了 CustomView 的對象。
下面是通知欄Target 與 AppWidgetTarget的使用
NotificationTarget target2=new NotificationTarget(context,
remoteview,
R.id.remoteview_notification_icon,
notification,
NOTIFICATION_ID);
Glide
.with( context.getApplicationContext() )
.load( url)
.asBitmap()
.into( notificationTarget );
public class MYAppWidgetProvider extends AppWidgetProvider {
private AppWidgetTarget appWidgetTarget;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews remoteviews= new RemoteViews(context.getPackageName(), R.layout.my_remoteView);
appWidgetTarget = new AppWidgetTarget( context, remoteviews, R.id.custom_view_image, appWidgetIds );
Glide
.with( context.getApplicationContext() ) // safer!
.load( GlideExampleActivity.eatFoodyImages[3] )
.asBitmap()
.into( appWidgetTarget );
pushWidgetUpdate(context, remoteviews);
}
public static void pushWidgetUpdate(Context context, RemoteViews remoteviews) {
ComponentName myWidget = new ComponentName(context, FSAppWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(myWidget, rv);
}
}
異常處理
Glide不提供直接獲取常規(guī)請求的日志,但是你可以在請求出錯(cuò)時(shí)抓取異常的日志。例如,如果圖片不存在,Glide會(靜靜地)拋出一個(gè)異常,并顯示出你.erroer()里指定的圖片。如果你明確想要知道異常,創(chuàng)建一個(gè)listener,然后傳遞給Glide的.listener()方法。
private RequestListener<String, GlideDrawable> requestListener = new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
// todo log exception
// important to return false so the error placeholder can be placed
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
};
Glide
.with( context )
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.listener( requestListener )
.error( R.drawable.cupcake )
.into( imageViewPlaceholder );
以上是Glide的基本使用
Glide源碼解析
從上面的一大串代碼中我們可以發(fā)現(xiàn),glide使用的是建造者模式
我們先看看with方法

with方法有很多的構(gòu)造函數(shù),可以傳入context、Activity等
Glide->with
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
Glide->getRetriever
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
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 Glide.get(context).getRequestManagerRetriever();//獲取 RequestManagerRetriever 對象
}
Glide->get
/**
* Get the singleton.
*
* @return the singleton
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
//這句是通過反射獲取com.bumptech.glide.GeneratedAppGlideModuleImpl并實(shí)例化
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {//單例模式
checkAndInitializeGlide(context, annotationGeneratedModule);//從名字上可以看出是初始化glide
}
}
}
return glide;
}
Glide->initializeGlide
@GuardedBy("Glide.class")
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
Glide->initializeGlide
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
...
Glide glide = builder.build(applicationContext);
...
}
GlideBuilder->build
Glide build(@NonNull Context context) {
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();//創(chuàng)建一個(gè)默認(rèn)的線程池,用來執(zhí)行耗時(shí)任務(wù)
}
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();//創(chuàng)建一個(gè)默認(rèn)的硬盤緩存線程池
}
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();//創(chuàng)建一個(gè)執(zhí)行動畫效果的線程池
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();//創(chuàng)建內(nèi)存緩存控制器,并設(shè)置其大小
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();//創(chuàng)建網(wǎng)絡(luò)監(jiān)聽器
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();//創(chuàng)建bitmap對象池
if (size > 0) { // 使用緩存
bitmapPool = new LruBitmapPool(size);
} else {// 不使用緩存
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);//在這里創(chuàng)建了requestManagerRetriever
最后創(chuàng)建一個(gè)請求管理類,將請求工廠對象傳入進(jìn)去,并且會實(shí)例化一個(gè)主線程的handler對象,用于主-子線程的切換
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps,
hardwareBitmapFdLimit,
minHardwareDimension);
}
}
RequestManagerRetriever
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
Glide->getRequestManagerRetriever
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() { //在這里我們看到直接返回了requestManagerRetriever對象
return requestManagerRetriever;
}
通過上面的方法,我們可以看到Glide已經(jīng)初始化完成了
現(xiàn)在已經(jīng)獲取到RequestManagerRetriever對象,接下來我們回到剛才的方法中,它調(diào)用了RequestManagerRetriever的get方法

從上圖可以看到,RequestManagerRetriever中有很多的get方法
RequestManagerRetriever->get
@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)) {//如果不是application的context就一直迭代這個(gè)方法
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper
// Only unwrap a ContextWrapper if the baseContext has a non-null application context.
// Context#createPackageContext may return a Context without an Application instance,
// in which case a ContextWrapper may be used to attach one.
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
//一直迭代這個(gè)方法,獲取到application的context,最后進(jìn)入到這個(gè)方法
return getApplicationManager(context);
}
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null /*parentHint*/);
}
}
public RequestManager get(Fragment fragment) {
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment);
}
}
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null /*parentHint*/);
}
}
public RequestManager get(View view) {
if (Util.isOnBackgroundThread()) {
return get(view.getContext().getApplicationContext());
}
Activity activity = findActivity(view.getContext());
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
他們會判斷Context是Activity的還是Fragment的調(diào)用對應(yīng)的方法,如果傳入的FragmentActivity或者Fragment,會調(diào)用supportFragmentGet,如果傳入的是Activity則調(diào)用fragmentGet,如果傳入的是view,則根據(jù)view中的context來判斷
他們的共同點(diǎn)是,如果isOnBackgroundThread是true,則會調(diào)用Application的方法
RequestManagerRetriever->getApplicationManager
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context.getApplicationContext());
//在這里獲取RequestManager 對象
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
@Deprecated
@NonNull
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
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) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
從上面代碼上看,傳入Activity 或者Fragment的context的最后都調(diào)用了getSupportRequestManagerFragment
@SuppressWarnings("deprecation")
@NonNull
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
SupportRequestManagerFragment的構(gòu)造函數(shù)創(chuàng)建了一個(gè)ActivityFragmentLifecycle對象用來管理生命周期,在onStart方法中調(diào)用ActivityFragmentLifecycle的onStart方法,同理其他生命周期方法也是。
public class SupportRequestManagerFragment extends Fragment {
private static final String TAG = "SupportRMFragment";
private final ActivityFragmentLifecycle lifecycle;
private final RequestManagerTreeNode requestManagerTreeNode =
new SupportFragmentRequestManagerTreeNode();
private final Set<SupportRequestManagerFragment> childRequestManagerFragments = new HashSet<>();
@Nullable private SupportRequestManagerFragment rootRequestManagerFragment;
@Nullable private RequestManager requestManager;
@Nullable private Fragment parentFragmentHint;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
/**
* Sets the current {@link com.bumptech.glide.RequestManager}.
*
* @param requestManager The manager to put.
*/
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
...
@Override
public void onDetach() {
super.onDetach();
parentFragmentHint = null;
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();
}
接下來我們看下RequestManager
RequestManager
public class RequestManager
implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
private static final RequestOptions DECODE_TYPE_BITMAP = decodeTypeOf(Bitmap.class).lock();
private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
private static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
diskCacheStrategyOf(DiskCacheStrategy.DATA).priority(Priority.LOW).skipMemoryCache(true);
protected final Glide glide;
protected final Context context;
@SuppressWarnings("WeakerAccess")
@Synthetic
final Lifecycle lifecycle;
@GuardedBy("this")
private final RequestTracker requestTracker;
@GuardedBy("this")
private final RequestManagerTreeNode treeNode;
@GuardedBy("this")
private final TargetTracker targetTracker = new TargetTracker();
private final Runnable addSelfToLifecycle =
new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
};
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private final ConnectivityMonitor connectivityMonitor;
// Adding default listeners should be much less common than starting new requests. We want
// some way of making sure that requests don't mutate our listeners without creating a new copy of
// the list each time a request is started.
private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;
@GuardedBy("this")
private RequestOptions requestOptions;
private boolean pauseAllRequestsOnTrimMemoryModerate;
public RequestManager(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode,
@NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),
glide.getConnectivityMonitorFactory(),
context);
}
// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
...
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
/**
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
@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);
}
...
在RequestManager實(shí)現(xiàn)了LifecycleListener接口,并且調(diào)用lifecycle.addListener(this)添加監(jiān)聽器。接口生命周期函數(shù)onStart()啟動請求,onStop暫停請求,在ActivtyFragmentLifecycle中如果添加了監(jiān)聽器,在onStart調(diào)用監(jiān)聽器的onStart方法,也就是調(diào)用RequsetManager中的onStart,同理onPause也是。
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
/**
* Adds the given listener to the list of listeners to be notified on each lifecycle event.
*
* <p>The latest lifecycle event will be called on the given listener synchronously in this
* method. If the activity or fragment is stopped, {@link LifecycleListener#onStop()}} will be
* called, and same for onStart and onDestroy.
*
* <p>Note - {@link com.bumptech.glide.manager.LifecycleListener}s that are added more than once
* will have their lifecycle methods called more than once. It is the caller's responsibility to
* avoid adding listeners multiple times.
*/
@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();
}
}
}
經(jīng)過上面的分析發(fā)現(xiàn)整個(gè)過程就理順了,先創(chuàng)建一個(gè)Fragment對象并在構(gòu)造函數(shù)中創(chuàng)建Lifecycle對象
,在創(chuàng)建RequestManager的時(shí)候會把Lifecycle對象傳遞進(jìn)去。RequestManger則在構(gòu)造函數(shù)處為接收的Lifecycle添加監(jiān)聽器,而RequestManager自身實(shí)現(xiàn)了LifecycleListener,在實(shí)現(xiàn)的接口方法onStop和onPause分別啟動和暫停請求。
Lifecycle對象在添加監(jiān)聽器后,會在生命周期方法onStart和onPauser分別調(diào)用監(jiān)聽器對應(yīng)的方法。
因此當(dāng)Fragment會在生命周期方法中調(diào)用Lifecycle對應(yīng)的生命周期方法,最終也就是在調(diào)用RequestManger中的生命周期方法,因此實(shí)現(xiàn)了請求和生命周期的綁定,從而可以根據(jù)生命周期來啟動和暫停請求。
總結(jié)一下,with()方法主要初始化Glide和創(chuàng)建了RequestManger綁定SupportRequestManagerFragment的生命周期函數(shù),最后返回RequestManager。
load方法

我們看到load方法有很多重載方法,load方法都實(shí)現(xiàn)自ModelTypes,經(jīng)過with方法,我們知道with方法返回的是requestManager對象,因此load方法在RequestManager方法中查找
RequestManager implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
...
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(Drawable)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
return asDrawable().load(drawable);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(String)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(Uri)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(File)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable File file) {
return asDrawable().load(file);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(Integer)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@SuppressWarnings("deprecation")
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return asDrawable().load(resourceId);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(URL)}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@SuppressWarnings("deprecation")
@CheckResult
@Override
@Deprecated
public RequestBuilder<Drawable> load(@Nullable URL url) {
return asDrawable().load(url);
}
/**
* Equivalent to calling {@link #asDrawable()} and then {@link RequestBuilder#load(byte[])}.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable byte[] model) {
return asDrawable().load(model);
}
/**
* A helper method equivalent to calling {@link #asDrawable()} and then {@link
* RequestBuilder#load(Object)} with the given model.
*
* @return A new request builder for loading a {@link Drawable} using the given model.
*/
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
...
我們可以發(fā)現(xiàn)無論哪個(gè)load方法都是調(diào)用了asDrawable()方法
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
public RequestBuilder<File> asFile() {
return as(File.class).apply(skipMemoryCacheOf(true));
}
public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}
public RequestBuilder<Bitmap> asBitmap() {
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}
我們可以看到,調(diào)用AS方法后里面實(shí)際上是初始化一個(gè)RequestBuilder對象
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
...
@SuppressLint("CheckResult")
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.glideContext = glide.getGlideContext();
initRequestListeners(requestManager.getDefaultRequestListeners());
apply(requestManager.getDefaultRequestOptions());
}
...
構(gòu)造了一個(gè)RequestBuilder實(shí)例,傳入的參數(shù)賦值到RequestBuilder的成員變量,這里成員transcodeClass也就是剛才的Drawable.class,記住了,初始化了一個(gè)requestOptions,這2個(gè)成員記住了,后面會有用的,接著回到之前的一段代碼,查看load方法
RequestBuilder->load
@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
return loadGeneric(drawable)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
return loadGeneric(uri);
}
public RequestBuilder<TranscodeType> load(@Nullable File file) {
return loadGeneric(file);
}
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
}
public RequestBuilder<TranscodeType> load(@Nullable URL url) {
return loadGeneric(url);
}
public RequestBuilder<TranscodeType> load(@Nullable byte[] model) {
RequestBuilder<TranscodeType> result = loadGeneric(model);
if (!result.requestOptions.isDiskCacheStrategySet()) {
result = result.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
if (!result.requestOptions.isSkipMemoryCacheSet()) {
result = result.apply(skipMemoryCacheOf(true /*skipMemoryCache*/));
}
return result;
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;//這個(gè)model就是url String 的實(shí)例
//數(shù)據(jù)來源是否已經(jīng)設(shè)置的標(biāo)志位 isModelSet 設(shè)置為true,意味著我們在調(diào)用 Glide.with(context).load(url) 之后數(shù)據(jù)來源已經(jīng)設(shè)置成功了。
isModelSet = true;
return this;
}
到這里其實(shí)load方法就已經(jīng)完了,還有一些其他的方法
public RequestBuilder<TranscodeType> apply(@NonNull RequestOptions requestOptions) {
Preconditions.checkNotNull(requestOptions);
this.requestOptions = getMutableOptions().apply(requestOptions);
return this;
}
public RequestBuilder<TranscodeType> transition(
@NonNull TransitionOptions<?, ? super TranscodeType> transitionOptions) {
this.transitionOptions = Preconditions.checkNotNull(transitionOptions);
isDefaultTransitionOptionsSet = false;
return this;
}
public RequestBuilder<TranscodeType> listener(
@Nullable RequestListener<TranscodeType> requestListener) {
this.requestListeners = null;
return addListener(requestListener);
}
public RequestBuilder<TranscodeType> addListener(
@Nullable RequestListener<TranscodeType> requestListener) {
if (requestListener != null) {
if (this.requestListeners == null) {
this.requestListeners = new ArrayList<>();
}
this.requestListeners.add(requestListener);
}
return this;
}
public RequestBuilder<TranscodeType> error(@Nullable RequestBuilder<TranscodeType> errorBuilder) {
this.errorBuilder = errorBuilder;
return this;
}
info(ImageView view)方法
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// Clone in this method so that if we use this RequestBuilder to load into a View and then
// into a different target, we don't retain the transformation applied based on the previous
// View's scale type.
switch (view.getScaleType()) {//這里獲取imageView的ScaleType屬性,glide會將ScaleType轉(zhuǎn)化成requestOptions
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
RequestBuilder->info
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request request = buildRequest(target, targetListener, options, callbackExecutor);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}