Glide的源码分析
glide作为android的图片加载框架,实现起来比较简便:
Glide.with(mActivity)
.load(newsBean.getNimg())-----load url to get image
.error(R.drawable.icon_scord)
.centerCrop()
.placeholder(R.drawable.icon_scord)
.into(viewHolder.ivIcon);
glide对图片的处理各方面个人认为还是不错的:
(1)支持Memory和Disk图片缓存。
(2)支持gif和webp格式图片。
(3)根据Activity/Fragment生命周期自动管理请求。
(4)使用Bitmap Pool可以使Bitmap复用。
*(5)对于回收的Bitmap会主动调用recycle,减小系统回收压力。
包括其内部机制:

1.
ok~进入正题 开始源码分析;先看requestManager的获取–Glide.with
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever =
RequestManagerRetriever.get();
return retriever.get(activity);
}
.with方法可以传入context/activty/fragment来获取requestManager,用法比较灵活;接下来继续看源码—->RequestManagerRetriever.get<即RequestManagerRetriever>
//getApplicationManager
private RequestManager getApplicationManager(Context context) {
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
applicationManager = new RequestManager
(context.getApplicationContext(),
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
//get
public RequestManager get(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 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);
}
//get
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.
getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
//supportFragmentGet
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
SupportRequestManagerFragment current=
getSupportRequestManagerFragment(fm);
RequestManager requestManager =
current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager
(context, current.getLifecycle(), current.
getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
//getSupportRequestManagerFragment
SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
SupportRequestManagerFragment current
= (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
在RequestManagerRetriever类中提供两个不同参的get方法,分别是get(context)/get(xxxActivity),获取fragment事务fm,同context一起传入supportFragmentGet()中;至于为什么还需要一个RequestManagerRetriever并有各种重载方法,主要是因为Glide通过SupportRequestManagerFragment和RequestManager关联了Activity或Fragment的生命周期,用来做pauseRequests等操作。
2.
接着来看Glide中.load(url)的放方法,
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class).
transition(new DrawableTransitionOptions());
}
public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide.getGlideContext(),
this, resourceClass);
}
看的出来load即是实现asDrawable().load(model);在load中加载的方法中最终返回RequestBuilder,在我看来可以理解为一个网络的构造器;大部分设置在RequestOptions里,这就是下面这一句:
apply(RequestOptions.placeholderOf(R.drawable.loading))
RequestOptions可以设置各种请求图片的相关选项;注意在这可以设置默认图片,加载失败的图片,包括各种加载策略等;RequestOptions继承自BaseRequestOptions,但全是工厂方法生成各种RequestOptions;<以后详解在这不做解释,只需要记得这可以设置一堆附加的属性等>
3.
然后看加载的发起点into方法。 //com.bumptech.glide.DrawableRequestBuilder:
//into(ImageView view)
@Override
public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
//com.bumptech.glide.GenericRequestBuilder:
//into(ImageView view)
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
if (view == null) {
throw new IllegalArgumentException("You must pass in a non null View");
}
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
//into(Y target)
public <Y extends Target<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
if (target == null) {
throw new IllegalArgumentException("You must pass in a non null Target");
}
if (!isModelSet) {
throw new IllegalArgumentException("You must first set a model (try #load())");
}
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);
return target;
}
Target是要加载到的目标<一般是holder中的ivIcon等字段>,参数为imageView,内部生成了一个DrawableImageViewTarget。这里最主要的操作是buildRequest然后交给RequestManager去track。—–>接下来看track的方法:
void track(Target<?> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
// class RequestTracker
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
TargetTrack中记录了所有正在加载的图片,通过方法requestTracker.runRequest(request);来判断加载过程的生命周期,如果!isPaused,这里相当于activity中onPause,如果!isPaused,则调用request.begin();开始加载,反之则进入队列即pendingRequests.add(request);进行加载等待… 除了设置缩略图的情景,使用的Request都是SingleRequest,看一下它的begin方法:
public void begin() {
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
看上面的代码,首先判断tarGet的大小,大小已知则调用 onSizeReady(overrideWidth, overrideHeight);进行下一步逻辑,如果不知道tartget大小则通过target.getSize(this);来获取tartget的大小,然后继续调用onSizeReady();onSizeReady()就是调用一下方法<通过一下方法实现逻辑>
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,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
ResourceCallback cb) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineJob<?> current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob<R> engineJob = engineJobFactory.build(key, isMemoryCacheable,
useUnlimitedSourceExecutorPool);
DecodeJob<R> decodeJob = decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
options,
engineJob);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(decodeJob);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
在Engine.load中,先loadFromCache,如果缓存没有命中就再loadFromActiveResources,这是两级内存缓存,第一级是LruCache,第二级是ActiveCache,主要作用是,有可能一个图片很早就被加载了,可能已经从LruCache被移除掉了,但这个图片可能还在被某一个地方引用着,也就是还是Active的,那它就可能在将来仍被引用到,所以就把它保留在二级的ActiveCache中,ActiveCache中是以弱引用引用图片的,并通过ReferenceQueue监测弱引用的回收,然后用Handler.IdleHandler在CPU空闲时被被回收的引用项从ActiveCache中移除。
接下来看对应的Key是否已经正在加载,如果是的话,就addCallback,这样如果有多个地方同时请求同一张图片的话,只会生成一个加载任务,并都能收到回调,这点是比Universal-Image-Loader好的地方。
正常的加载流程是生成一个EngineJob和一个DecodeJob,通过engineJob.start(decodeJob)来进行实际的加载。
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
EngineJob.start直接将DecodeJob交给Executor去执行了(DecodeJob实现了Runnable接口)。DecodeJob的加载操作放到了runWrapped中
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
return Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
以上三步即为gide.with(xxx).load(xxx).into(xxx)的源码,了解源码的你相信会更加熟练的使用Glide