Glide 源码解析
如果想看
Glide
缓存机制的话,
点击这里。
当源码量大难懂的时候,看源码的思路:
- 只管主线,不管支线,不管支线,不管支线!(这次只看主线)
- 重点在主线,稍微瞄一眼支线。
- 稍微分析支线,回顾主线。
- 分析支线细节,回顾主线。
- 分析支线细节,寻找答案。
本次解析是基于
Glide-4.11.0
版本。
Glide.with(this).load(url).into(imageView).
-
with
创建一个空白的Fragment
,来管理生命周期。 -
load
创建一个RequestBuilder
对象。 -
into
主要做了一下功能:
- 运行队列,等待队列
- 活动缓存
- 内存缓存
- 网络模型
Glide
的核心是:生命周期,缓存机制
Glide流程简化图
问题
- 为什么去监听生命周期?
答:方便资源的及时回收。
- 项目中大量使用
Glide
时,偶尔会出现内存泄漏的问题,大概是什么原因?
答:在用with
的时候,尽量使用非application
作用域,才能进行生命周期的监听,及时回收及释放等操作。
Glide.with()
在子线程加载时有什么问题?
答:不会添加空fragment
监听生命周期,主线程才会添加。
Glide
的缓存为什么要有活动缓存和内存缓存?
答:活动缓存:页面正在显示的图片,必须访问的。内存缓存:LRU
机制。都是运行时缓存。
如果页面在显示内存里的缓存图片,但这时LRU
机制删除了这个缓存,彻底释放资源,就会报错。
所以制定了活动缓存,来存放页面必须用到的缓存。如果用到的缓存在内存缓存则会先移动到活动缓存中。
如果页面关闭掉,活动缓存中数据会再次移动到内存缓存中,等待下次使用。
with
子线程:application
作用域,不会创建空白的Fragment
。
主线程:非application
作用域,会创建空白的Fragment
。
绑定Fragment
的时候,第一层判定会先从栈中通过TAG
获取是否有fragment
, map
对fragment
进行缓存作为第二层判定。
@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通知移除集合,因为fragment的commit就是通过handler执行,
当handleMessage接收到移除集合的消息,说明fragment commit已经执行了。
并且避免了内存泄漏。
*/
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER,fm).sendToTarget();
}
}
return current;
}
lifecycle (add,remove LifecycleListener)
–>ApplicationLifecycle
(绑定Application
生命周期),ActivityFragmentLifecycle
(绑定空白Fragment
生命周期)
RequestManager
实现LifecycleListener
接口,去通知其他类生命周期的改变。
public class RequestManager implements LifeCycleListener{
/**
* 开始所有任务
* 运行队列全部开始执行,等待队列全部清空
*/
@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);
}
}
Load
主要返回一个 RequestBuilder
对象。待完善…
into
主线大致流程:
ImageViewTarget
(显示图片), 无论走多远,一定回到这里。
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
// 省略...
return into(
// 构建ImageViewTarget对象
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
在上面的return
的into
方法中,会有下面的代码:
Request request = buildRequest(target, targetListener, options, callbackExecutor);
而buildRequest
最终创建的是SingleRequest
。这里面层级很深。这里只展示最终创建SingleRequest
的地方。
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
// 享元设计模式
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
- 经过
requestManager.track()
–>requestTracker.runRequest(request)
–>request.begin()
–>Request
的实现类SingleRequest.begin()
方法。在begin()
方法中,会有下面的判断:
// 用户是否设置了宽和高
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight); // 设置了宽高
} else {
// 用户没有设置宽和高,会再次测量-->再次调用onSizeReady
target.getSize(this);
}
onSizeReady()
–>engine.load()
,load
里面会有加载缓存的判断:
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor) {
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
// 1.构建key
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
EngineResource<?> memoryResource;
synchronized (this) {
// 2.loadFromMemory会先后从 活动缓存和内存缓存 获取缓存
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// 没有缓存
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}
// 命中缓存,回调给外界
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
return null;
}
其中,活动缓存:页面正在显示的图片,必须访问的。内存缓存:LRU
机制。(这里不详细说了)
5.waitForExistingOrStartNewJob()
方法中会有
private <R> LoadStatus waitForExistingOrStartNewJob(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb,
Executor callbackExecutor,
EngineKey key,
long startTime) {
// 1.是否有正在运行的任务
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// 1.EngineJob是线程池大管家
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
// 2.执行的任务
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
engineJob.start(decodeJob)
会执行decodeJob
中的run
方法,run()-->runWrapped()-->getNextGenerator()
默认会返回SourceGenerator
–>runGenerators()
–>SourceGenerator .startNext()
–>helper.getLoadData()
{–>modelLoader.buildLoadData()
–>HttpGlideUrlLoader.buildLoadData()
–>new LoadData<>(url, new HttpUrlFetcher(url, timeout))-HttpUrlFetcher
做网络请求 }- 从上面的
SourceGenerator .startNext()
继续-->startNextLoad()-->HttpUrlFetcher.loadData()
public void loadData() {
//loadDataWithRedirects方法就是网络请求
InputStream result = loadDataWithRedirects(
glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
}
result
会一层一层向上回调,一层一层包装,onDataReady(result)-
->SourceGenerator .onDataReadyInternal()-
->DecodeJob.onDataFetcherReady()
–>decodeFromRetrievedData()
–>decodeFromData()-
->decodeFromFetcher()
–>runLoadPath()
–>path.load()
–>loadWithExceptionList()
–>path.decode()–>decodeResource()
–>decodeResourceWithList()
–>decoder.decode()
–>StreamBitmapDecoder.decode()
返回值Resource<Bitmap>
终于把stream
转变为了Bitmap
。
// 这里的Resource<Transcode>会被转成Resource<Bitmap>
public Resource<Transcode> decode(
DataRewinder<DataType> rewinder,
int width,
int height,
@NonNull Options options,
DecodeCallback<ResourceType> callback)
throws GlideException {
// 把stream转变为了Bitmap
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
// 回调
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
- 然后回调会一层一层向上,并且会对
bitmap
进行各种操作,具体的链路不写了(妈的已经崩溃了…)。最终会会掉到ImageViewTarget
去显示图片。
总结
Glide
的源码看着很痛苦,非常多细节没有补充,有可能有不对的地方,希望大家能指正。在后续的学习中也会不断的完善。