前言
關(guān)于Glide的優(yōu)缺點(diǎn)和使用劳闹,這里不在闡述碾牌,具體請(qǐng)看GitHub上官方介紹曹阔。這里主要結(jié)合別人的文章和自己看源碼的一些見(jiàn)解茉盏,分享一下自己的理解鉴未。Glide龐大的圖片庫(kù)做的封裝性極好支持的格式也很多,開(kāi)發(fā)者的代碼設(shè)計(jì)嚴(yán)格遵守了軟件設(shè)計(jì)的六大原則鸠姨,一開(kāi)始看的時(shí)候感覺(jué)結(jié)構(gòu)好麻煩铜秆,好多接口,好多回調(diào)讶迁,后來(lái)細(xì)想了一下這些都是軟件設(shè)計(jì)的六大原則約束连茧,帶來(lái)的好處就是低耦合,易維護(hù)巍糯,等等很多優(yōu)點(diǎn)啸驯,我會(huì)在分析的時(shí)候講一下里邊設(shè)計(jì)的設(shè)計(jì)模式。
整個(gè)Glide的流程圖
如下是一張大概的流程圖
發(fā)現(xiàn)的問(wèn)題
自定義AppGlideModule中applyOptions方法設(shè)置默認(rèn)圖片格式PREFER_RGB_565無(wú)效祟峦,查看源碼會(huì)發(fā)現(xiàn)在glide在解碼圖片的時(shí)候罚斗,會(huì)根據(jù)解析圖片頭得到的圖片格式設(shè)置解碼格式:Png格式圖片設(shè)置為PREFER_ARGB_8888,jpg格式的圖片設(shè)置為PREFER_RGB_565宅楞。
-驗(yàn)證方法
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
//設(shè)置格式為565
builder.setDefaultRequestOptions(RequestOptions.formatOf(DecodeFormat.PREFER_RGB_565));
}
}
在MainActivity中通過(guò)如下方式打印一下圖片的格式
Glide.with(this).asBitmap().addListener(new RequestListener<Bitmap>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
Bitmap.Config config = resource.getConfig();
Log.i("jawe", "onResourceReady: config="+config);
return false;
}
}).load("http://d.lanrentuku.com/down/png/1904/international_food/fried_rice.png").into(imageView);
這里打印出來(lái)的config就是ARGB_8888
-查看源碼
具體在Downsample.java的calculateConfig方法內(nèi)
private void calculateConfig(
....){
....
...
boolean hasAlpha = false;
try {
hasAlpha = ImageHeaderParserUtils.getType(parsers, is, byteArrayPool).hasAlpha();
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(
TAG,
"Cannot determine whether the image has alpha or not from header"
+ ", format "
+ format,
e);
}
}
//這里根據(jù)是否有透明度設(shè)置解碼格式
optionsWithScaling.inPreferredConfig =
hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
if (optionsWithScaling.inPreferredConfig == Config.RGB_565) {
optionsWithScaling.inDither = true;
}
}
主流程分析
一般的使用如下:
Glide.with(this).load("http://d.lanrentuku.com/down/png/1904/international_food/fried_rice.png") .apply(new RequestOptions().error(R.drawable.ic_launcher_background).placeholder (R.mipmap.ic_launcher).override(500, 500)).into(iv);
越是看起來(lái)很簡(jiǎn)單的代碼针姿,背后的封裝性很復(fù)雜,下面我們就一步步分析一下
Glide.with做的事情
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
//1.getRetriever(activity)得到RequestManager檢索器
//2.通過(guò)檢索器得到一個(gè)RequestManager
return getRetriever(activity).get(activity);
}
@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.
return Glide.get(context).getRequestManagerRetriever();
}
其中Glide.get(context)得到的是Glide單例對(duì)象厌衙,然后getRequestManagerRetriever();得到檢索器
private static volatile Glide glide;
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
這里采用的雙重校驗(yàn)加鎖(DCL)的方式實(shí)現(xiàn)單例模式,其中g(shù)lide使用volatile修飾加入內(nèi)存屏障距淫,禁止指令重排序,使得其他線程的修改能被直接讀取最新值婶希,即高并發(fā)時(shí)候線程的可見(jiàn)性溉愁。
Glide在V4中推薦使用注解的方式配置Glide選項(xiàng),Glide在創(chuàng)建Glide對(duì)象的時(shí)候會(huì)根據(jù)編譯期生成的RequestManagerRetriever.RequestManagerFactory設(shè)置Glide然后調(diào)用Glide glide = builder.build(applicationContext);創(chuàng)建Glide對(duì)象。
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
...
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
builder.setRequestManagerFactory(factory);
...
Glide glide = builder.build(applicationContext);
...
Glide.glide = glide;
這里邊其中GlideBuilder內(nèi)部實(shí)現(xiàn)了很多默認(rèn)的Glide配置拐揭,我們一起看看
/** A builder class for setting default structural classes for Glide to use. */
@SuppressWarnings("PMD.ImmutableField")
public final class GlideBuilder {
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
private Engine engine;//加載引擎
private BitmapPool bitmapPool;//bitmap復(fù)用池
private ArrayPool arrayPool;//array復(fù)用池
private MemoryCache memoryCache;//內(nèi)存緩存
private GlideExecutor sourceExecutor;//source線程池
private GlideExecutor diskCacheExecutor;//磁盤緩存線程池
private DiskCache.Factory diskCacheFactory;//磁盤緩存工廠
private MemorySizeCalculator memorySizeCalculator;//緩存大小計(jì)算器
private ConnectivityMonitorFactory connectivityMonitorFactory;
private int logLevel = Log.INFO;
private RequestOptionsFactory defaultRequestOptionsFactory =
new RequestOptionsFactory() {
@NonNull
@Override
public RequestOptions build() {
return new RequestOptions();
}
};
@Nullable private RequestManagerFactory requestManagerFactory;//requestManager工廠
private GlideExecutor animationExecutor;
...
}
通過(guò)注釋可以很清楚的知道這個(gè)類的作用就是用來(lái)構(gòu)建Glide撤蟆,這里也可以看出使用了構(gòu)建者模式(builder),將復(fù)雜對(duì)象的表示和它的實(shí)現(xiàn)分離。
我們看一下build方法
Glide build(@NonNull Context context) {
//GlideExecutor創(chuàng)建線程池,這里我把GlideExecutor理解是一個(gè)工具類
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
...
...
//根據(jù)設(shè)備內(nèi)存大小計(jì)算最優(yōu)的內(nèi)存堂污,復(fù)用池家肯,磁盤緩存大小等
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
......
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);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps,
hardwareBitmapFdLimit,
minHardwareDimension);
}
這里體現(xiàn)了設(shè)計(jì)模式種的單一職責(zé)模式,builder里邊主要做的事情:
1.根據(jù)不同的任務(wù)特性結(jié)合設(shè)備的cpu等特征設(shè)置不同的線程池
2.根據(jù)設(shè)備的內(nèi)存和磁盤大小設(shè)置最優(yōu)的內(nèi)存和磁盤大小盟猖,以及構(gòu)建復(fù)用池
3.構(gòu)建加載引擎(Engine)
4.構(gòu)建Glide對(duì)象
我們接下來(lái)看一下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,
int minHardwareDimension) {
...
registry
/** 編碼器 磁盤緩存使用的*/
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
/* Bitmaps 注冊(cè)解碼器 使用byteBufferBitmapDecoder從ByteBuffer 解碼成bitmap */
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
.append(
Registry.BUCKET_BITMAP,
ParcelFileDescriptor.class,
Bitmap.class,
parcelFileDescriptorVideoDecoder)
.append(
Registry.BUCKET_BITMAP,
AssetFileDescriptor.class,
Bitmap.class,
VideoDecoder.asset(bitmapPool))
.append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance())
.append(Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
/**注冊(cè) bitmap的編碼器 用于磁盤緩存*/
.append(Bitmap.class, bitmapEncoder)
/* BitmapDrawables */
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
ByteBuffer.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
InputStream.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
ParcelFileDescriptor.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder))
.append(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, bitmapEncoder))
/* GIFs */
.append(
Registry.BUCKET_GIF,
InputStream.class,
GifDrawable.class,
new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
.append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
.append(GifDrawable.class, new GifDrawableEncoder())
/* GIF Frames */
// Compilation with Gradle requires the type to be specified for UnitModelLoader here.
.append(
GifDecoder.class, GifDecoder.class, UnitModelLoader.Factory.<GifDecoder>getInstance())
.append(
Registry.BUCKET_BITMAP,
GifDecoder.class,
Bitmap.class,
new GifFrameResourceDecoder(bitmapPool))
/* Drawables */
.append(Uri.class, Drawable.class, resourceDrawableDecoder)
.append(
Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitmapPool))
/* Files 文件解碼器 */
.register(new ByteBufferRewinder.Factory())
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
.append(File.class, InputStream.class, new FileLoader.StreamFactory())
.append(File.class, File.class, new FileDecoder())
.append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
// Compilation with Gradle requires the type to be specified for UnitModelLoader here.
.append(File.class, File.class, UnitModelLoader.Factory.<File>getInstance())
/* Models 網(wǎng)絡(luò) */
.register(new InputStreamRewinder.Factory(arrayPool))
.append(int.class, InputStream.class, resourceLoaderStreamFactory)
.append(int.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory)
.append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
.append(Integer.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory)
.append(Integer.class, Uri.class, resourceLoaderUriFactory)
.append(int.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory)
.append(Integer.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory)
.append(int.class, Uri.class, resourceLoaderUriFactory)
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
.append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(
String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
.append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
.append(
Uri.class,
ParcelFileDescriptor.class,
new AssetUriLoader.FileDescriptorFactory(context.getAssets()))
.append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
.append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
.append(Uri.class, InputStream.class, new UriLoader.StreamFactory(contentResolver))
.append(
Uri.class,
ParcelFileDescriptor.class,
new UriLoader.FileDescriptorFactory(contentResolver))
.append(
Uri.class,
AssetFileDescriptor.class,
new UriLoader.AssetFileDescriptorFactory(contentResolver))
.append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
.append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
.append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
.append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
.append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
.append(Uri.class, Uri.class, UnitModelLoader.Factory.<Uri>getInstance())
.append(Drawable.class, Drawable.class, UnitModelLoader.Factory.<Drawable>getInstance())
.append(Drawable.class, Drawable.class, new UnitDrawableDecoder())
/* Transcoders 轉(zhuǎn)碼器 */
.register(Bitmap.class, BitmapDrawable.class, new BitmapDrawableTranscoder(resources))
.register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
.register(
Drawable.class,
byte[].class,
new DrawableBytesTranscoder(
bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
.register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
...
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
構(gòu)造方法內(nèi)部核心就是把所需要的編碼器讨衣,解碼器,加載模型式镐,轉(zhuǎn)碼器都注冊(cè)到注冊(cè)表中反镇,以供后邊加載圖片 緩存圖片的時(shí)候使用。這里解釋一下Glide中的組件以及作用:
1.ModelLoader, 將自定義的 Model(Url,File, Uri,任意的 POJO )加載成 Data(InputStreams, FileDescriptors)娘汞。
2.ResourceDecoder, 將 Data 類型(InputStreams, FileDescriptors)進(jìn)行解碼成新的 Resources(Drawables, Bitmaps)
3.Encoder, 用于向 Glide 的磁盤緩存寫 Data (InputStreams, FileDesciptors)歹茶。
4.ResourceTranscoder,用于在不同的資源類型之間做轉(zhuǎn)換你弦,例如惊豺,從 BitmapResource 轉(zhuǎn)換為 DrawableResource 。
5.ResourceEncoder禽作,用于向 Glide 的磁盤緩存寫 Resources(BitmapResource, DrawableResource)尸昧。
RequestManagerRetriever#get(activity)
構(gòu)建RequestManger對(duì)象
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
這里是在主線程中執(zhí)行的,所以執(zhí)行else條件
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(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;
}
這里可以看出RequestManager 綁定一個(gè)SupportRequestManagerFragment
@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;
}
當(dāng)前的頁(yè)面綁定一個(gè)隱藏?zé)o界面的Fragment旷偿,來(lái)感知組件的生命周期烹俗,這樣做的目的是避免內(nèi)存泄漏,如果activity頁(yè)面中使用Glide加載一張圖片萍程,activity被用戶關(guān)掉了衷蜓,但是Glide單例中的ViewTarget還在引用ImageView對(duì)象,而ImageView對(duì)象又引用activity對(duì)象尘喝,那么這個(gè)activity對(duì)象就不會(huì)被回收掉,也就是內(nèi)存泄漏了斋陪。這里可以看出一個(gè)fragmentManager只有一個(gè)fragment朽褪。
注意這里有一個(gè)疑問(wèn),為什么要用handler發(fā)送消息的形式移除fm无虚,這里看起來(lái)沒(méi)有線程切換缔赠,完全可以直接移除。關(guān)于這個(gè)問(wèn)題我問(wèn)了我的同事友题,同事的解釋是正確的嗤堰,因?yàn)閏ommitAllowingStateLoss 這個(gè)事務(wù)是異步執(zhí)行的,為了保證一個(gè)fragmentManager只有一個(gè)綁定的SupportRequestManagerFragment度宦,所以添加一個(gè)集合控制邏輯踢匣,當(dāng)?shù)谝淮翁峤皇聞?wù) 異步執(zhí)行的時(shí)候告匠,如果用戶接著第二次get的時(shí)候,findFragmentByTag是null(前邊的fragment還沒(méi)有掛載到activity上)這時(shí)候從集合中查到了离唬,就返回去后专。但是如果不從集合中移出去就會(huì)內(nèi)存泄漏,為了保證是在掛載成功后输莺,從集合中移掉fm戚哎,所以使用handler發(fā)送消息,利用handler的消息機(jī)制嫂用,消息隊(duì)列排隊(duì)取出消息處理的型凳,所以移除的動(dòng)作是在commit后執(zhí)行的。
RequestManager
- 介紹:RequestManager是Glide中管理和啟動(dòng)Request的一個(gè)類嘱函,可以感知組件生命周期甘畅,不同的周期采用不同的管理策略。
- 分析:前邊的分析看到RequestManager是通過(guò)工廠構(gòu)建產(chǎn)生的实夹,注解生成默認(rèn)的工廠是new方式創(chuàng)建對(duì)象
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);//1
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
這里最重要的就是注釋1處橄浓,把requestManger當(dāng)前對(duì)象添加到lifecycle的監(jiān)聽(tīng)接口中,這個(gè)lifecycle就是前邊在構(gòu)建SupportRequestManagerFragment對(duì)象的時(shí)候構(gòu)建出來(lái)的ActivityFragmentLifecycle亮航,而ActivityFragmentLifecycle 就是一個(gè)觀察者荸实,觀察Fragment的生命周期,然后通知所有的訂閱者(LifecycleListener)缴淋,訂閱者其中就有RequestManager准给,看一下ActivityFragmentLifecycle
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();
}
}
...
}
其中addListener內(nèi)部就像一個(gè)粘性事件一樣,添加訂閱的時(shí)候重抖,能夠訂閱到訂閱前的信息露氮。
內(nèi)存管理
Android是一個(gè)內(nèi)存很敏感的應(yīng)用,當(dāng)系統(tǒng)內(nèi)存不足的時(shí)候钟沛,就會(huì)殺死一些進(jìn)程回收內(nèi)存畔规。為了讓應(yīng)用存活更久,Glide做了內(nèi)存優(yōu)化恨统,其中Glide 實(shí)現(xiàn)了ComponentCallbacks2接口并且在onTrimMemory(int level)中根據(jù)不同的級(jí)別做出相應(yīng)的內(nèi)存管理叁扫。
public void trimMemory(int level) {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// Request managers need to be trimmed before the caches and pools, in order for the latter to
// have the most benefit.
for (RequestManager manager : managers) {
manager.onTrimMemory(level);
}
// memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
memoryCache.trimMemory(level);
bitmapPool.trimMemory(level);
arrayPool.trimMemory(level);
}
總結(jié)
Glide.with(activity)采用的外觀設(shè)計(jì)模式,創(chuàng)建Request Manger對(duì)象 能夠根據(jù)組件生命周期的不同階段畜埋,來(lái)暫停莫绣,啟動(dòng),停止請(qǐng)求悠鞍,請(qǐng)求的處理流程requestTrack中管理的对室。Glide.with的流程圖如下: