重学Android——Glide4.x源码分析(2)
Glide4.x
先来说下世面上常用的三种图片加载框架Picasso,Glide,Fresco
Picasso与Glide相比:
- 相似——api上的调用差不多,都支持内存缓存,glide是picasso的升级,性能有一定的提升
- 差异
- 缓存不同,picasso2级缓存,没有磁盘缓存,Glide三级缓存,内存-磁盘-网络的优先级加载黑乎乎。
- Picasso默认加载的图片格式是ARGB-8888,Glide默认是RGB-565,内存开销节省小一半
- Picasso是加载全尺寸图片到内存中,下次在任何imageView中加载图片时,先取全尺寸图片,重新调整大小,再存缓存。而Glide是按ImageView的大小缓存的,为每种大小缓存一次。Glide这种方式是空间换时间,大小几乎是picasso的2倍
- 生命周期问题,Glide的with方法图片加载会和Activity与Fragment的生命周期一致
- Glide可以加载GIF
- Picasso包特别小,100k左右,方法法为850,glide大概500k,2700个方法。
Fresco
- 优点:
- 图片存储在安卓系统匿名共享内存区,而不是虚拟机的堆内存,图片的中间缓冲数据也存放在本地堆内存,所以应用有更多的内存空间使用。不容易OOM,减少GC回收
- 渐近式加载,支持图片从模糊到清晰,用户体验极好
- 图片可以以任意为中心点显示在ImageView
- JPEG图片改变大小也是在native进行,不在虚拟机堆内存,同样减少OOM
- 对GIF支持友好
- 缺点
- 包太大,2-3M
- 用法复杂
- 底层都是C/C++,源码阅读有挑战性
小结
Glide能做Picasso能做的所有事情,更快,能处理大型图片流,一般Glide是首选;Fresco当使用图片非常多的应用时,它的优势非常明显
Glide的基本使用
implementation ("com.github.bumptech.glide:glide:4.9.0") {
exclude group: "com.android.support"
}
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
复制代码
Glide.with(this)
.load("http://pic37.nipic.com/20140113/8800276_184927469000_2.png")
.into(imageView);
"android.permission.INTERNET" />
复制代码
需要注意的是,我们在Android9.0以上使用,用的http请求的话,需要在AndroidMainfest中
"true">
复制代码
原因是android9.0以后,默认禁止http请求的。
Glide源码
Glide.with(实例化Glide并获取RequestManager)
先看Glide.with()方法
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
复制代码
可以看到,with方法有多个重载方法,而且都是先调用了getRetriever
这个方法,那么我们先看这个方法的源码
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
...
return Glide.get(context).getRequestManagerRetriever();
}
复制代码
从源码看,直接是调用Glide的get()方法,然后再调用getRequestManagerRetriever
先看get方法
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
复制代码
一看原来Glide是单例,只有第一次会实例化,通过Builder模式实例化Glide对象,初始化后调用getRequestManagerRetriever方法来得到RequestManagerRetriever对象。
生命周期管理
那么问题又回到了getRetriever(xxx).get(xxx);这里,当getRetriever得到了RequestManagerRetriever对象,我们继续看后面的get方法
//get方法也和with一样,有多个对应的重载
@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)) {
//直接返回ApplicationManager
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());
}
}
//传入的context为ApplicationContext
return getApplicationManager(context);
}
//get(Activity/fragement)逻辑都差不多的,这里只拿getFragmentActivity来讲
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
//后台时,就调用get(context)
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
//前台可见,创建一个FragmentManager
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
//获取RequestManager
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为空,创建requestManager,并把Lifecycle传了进去
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//缓存这个requestManager
current.setRequestManager(requestManager);
}
return requestManager;
}
//创建并添加一个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);
//在这里,使用fragmentManager添加了一个隐藏的无界面Fragment
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
复制代码
可以看到,get方法的重载方法很多,但是核心都是一样的的,就是返回两种requestManager,1. ApplicationManager,它的生命周期与应用同步,应用退出,Glide也退出;2. 附加在Fragment之上的requestManager,通过这个fragment,绑定了对应的生命周期,这样就可以在Activity销毁时往上加载了,RxPermission也是这么设计的。
public class SupportRequestManagerFragment extends Fragment {
private static final String TAG = "SupportRMFragment";
private final ActivityFragmentLifecycle lifecycle;
...
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
registerFragmentWithRoot(getActivity());
} catch (IllegalStateException e) {
// OnAttach can be called after the activity is destroyed, see #497.
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to register fragment with root", e);
}
}
}
@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();
}
...
}
复制代码
可以看到,SupportRequestManagerFragment就是这么设计的,注入了一个生命周期监听器ActivityFragmentLifecycle,并在Fragment的各个生命周期中,调用了对应的方法。
class ActivityFragmentLifecycle implements Lifecycle {
...
@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();
}
}
}
复制代码
可以看到,在ActivityFragmentLifecycle会紧接着调用lifecycleListener监听器,而这个监听器其实就是RequestManager。
最后,可以看到,生命周期已与requestManager进行了绑定。
RequestBuilder
load
接下来我们看load方法的源码
public RequestBuilder load(@Nullable String string) {
return asDrawable().load(string);
}
复制代码
先来看前面的asDrawable
public RequestBuilder asDrawable() {
return as(Drawable.class);
}
public RequestBuilder as(
@NonNull Class resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
复制代码
其实就相当于new RequestBuilder,那再看load
public RequestBuilder load(@Nullable String string) {
return loadGeneric(string);
}
@NonNull
private RequestBuilder loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
复制代码
可以看到load方法非常简单,其实是创建了RequestBuilder,并把传递进来的参数url赋值给RequestBuilder中。
into方法实现资源加载并设置到target中
再看into方法
public ViewTarget 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.
//这些都与ImageView的scaleType相关,是转换逻辑,与我们关心的代码流程无关,可以不用关心
switch (view.getScaleType()) {
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());
}
复制代码
分析源码可以知道,它的内部调用了into的重载方法
我们先看里面的参数方法glideContext.buildImageViewTarget(view, transcodeClass),
@NonNull
public ViewTarget buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
public ViewTarget buildTarget(@NonNull ImageView view,
@NonNull Class clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
复制代码
可以看到,返回了ViewTarger,还记得上面我们看到的asDrawable么,说明是DrawableImageViewTarget,接下来再看外层的into方法
private > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener,
BaseRequestOptions> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//创建request
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//获取targert之前的请求任务(如果有的话)
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
//新构建的request上一个相等,并且设置了缓存以及没有执行完成
//释放新的request
request.recycle();
// 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()) {
//当旧的request没有在运行。执行它的begin
// 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;
}
// 清除先Target之前的所有任务并释放资源
requestManager.clear(target);
//把新的request设置给target
target.setRequest(request);
//在这里执行request,下载图片任务
requestManager.track(target, request);
return target;
}
private boolean isSkipMemoryCacheWithCompletePreviousRequest(
BaseRequestOptions> options, Request previous) {
//是否设置缓存以及上一次是否执行完成
return !options.isMemoryCacheable() && previous.isComplete();
}
复制代码
这里主要做了两件事:
- 通过buildRequest构建了一个request
- 获取target的上一个request对象,与新的request对比,并检测是否采用了缓存及target的上次请求是否完成
- 两个对象相等,并且options采用了缓存或target上一次没有请求完,则将新的request回收,并判断target的request是否还在运行,没有的话begin,并返回
- 两个对象不相等,或者option没有使用缓存和target请求完成了,清除target的之间设置,并将新的request对象设置给target,通过track方法启动request请求。
再来看requestManager的track方法
synchronized void track(@NonNull Target> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
public void track(@NonNull Target> target) {
targets.add(target);
}
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
//当处于前台可见时,调用request的begin
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
//先不执行request,只把它加入到一个准备队列
pendingRequests.add(request);
}
}
复制代码
可的看到,track方法是先将target添加到targetTracker类的targets集合中,然后运行request的begin方法。
到这里,其实图片加载网络资源的流程已经完成了大半了。接下来接着看如何加载资源并显示到target上的。
Request实现加载资源及显示
我们直接点request.begin方法去跟踪源码,会发现Request只是一个接口,所以我们要找到它的实现类。
那么我们再看上面的创建request方法
private Request buildRequest(
Target target,
@Nullable RequestListener targetListener,
BaseRequestOptions> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
//参数是真鸡儿长
private Request buildRequestRecursive(
Target target,
@Nullable RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions> requestOptions,
Executor callbackExecutor) {
...
//关键代码
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
if (errorRequestCoordinator == null) {
return mainRequest;
}
...
//如果有设置错误时的处理逻辑
return errorRequestCoordinator;
}
复制代码
可以看到,真正的核心代码在buildThumbnailRequestRecursive方法
//这个方法结构其实很简单,但是参数太多,所以把参数省略再看
private Request buildThumbnailRequestRecursive(
...) {
//默认的thumbnailBuilder就是空的,除非手动调用RequestBuilder类的thumbnail方法
//否则这个if代码块永远执行不到
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a "
+ "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
}
TransitionOptions, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
//缩略图权限
Priority thumbPriority = thumbnailBuilder.isPrioritySet()
? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);
//缩略图宽高
int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
//宽高检验
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
//缩略图请求协议器,同时协调原图与缩略图的request
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
//原图请求
Request fullRequest =
obtainRequest(...);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
//调用buildRequestRecursive,还是会调到buildThumbnailRequestRecursive,这是个递归方法
//递归生成缩略图请求
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(...);
isThumbnailBuilt = false;
//把这两个request包装到ThumbnailRequestCoordinator中
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
//根据指定的缩放系数加载缩略图
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(...);
BaseRequestOptions> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(...);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
//只加载原图
// Base case: no thumbnail.
return obtainRequest(...);
}
}
复制代码
可以看到,在buildThumbnailRequestRecursive主要做了有无缩略图的判断,然后再进行加载,最后调用了obtainRequest方法
private Request obtainRequest(
Target target,
RequestListener targetListener,
BaseRequestOptions> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
return SingleRequest.obtain(
context,
glideContext,
model,//对应load(url),比如一个图片地址
transcodeClass,
requestOptions,
overrideWidth,//宽
overrideHeight,//高
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),//全局加载引擎
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
复制代码
这个方法通过SingleReques
类的方法obtain去创建一个Request对象,所以,它就是我们要找的requst,那么看它的begin方法
开启资源加载任务
@Override
public synchronized void begin() {
assertNotCallingCallbacks();
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;
}
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
// If we're restarted after we're complete (usually via something like a notifyDataSetChanged
// that starts an identical request into the same Target or View), we can simply use the
// resource and size we retrieved the last time around and skip obtaining a new size, starting a
// new load etc. This does mean that users who want to restart a load because they expect that
// the view size has changed will need to explicitly clear the View or Target before starting
// the new load.
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
// Restarts for requests that are neither complete nor running can be treated as new requests
// and can run again from the beginning.
status = Status.WAITING_FOR_SIZE;
//如果Target的宽高已经获取并合法,就开始下一步
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 (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
复制代码
可以看到,begin方法经过一系列的判断,当status是RUNNING或者WAITING_FOR_SIZE状态,并且需要设置占位图时,会调用onLoadStarted设置占位图,当状态是COMPLETE时,会执行onResourceReady方法并返回。
@Override
public synchronized void onResourceReady(Resource> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
loadStatus = null;
...
//判断是否需要设置资源,如果不需要就直接释放并设置状态为COMPLETE
if (!canSetResource()) {
releaseResource(resource);
// We can't put the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
//执行方法
onResourceReady((Resource) resource, (R) received, dataSource);
}
复制代码
上面省略了一大段加载失败的代码,直接来看onResourceReady的重载方法。
private synchronized void onResourceReady(Resource resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
...
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
//设置资源及动画相关的信息
if (!anyListenerHandledUpdatingTarget) {
Transition super R> animation =
animationFactory.build(dataSource, isFirstResource);
//这个target有多个,比如DrawableImageViewTarget
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
//最后通知加载成功
notifyLoadSuccess();
}
复制代码
可以看到,当状态为COMPLETE时,就是把当前result设置到当前的target上,并通知加载成功(做一些加载成功后的清理工作)。
上面是COMPLETE时的状态,那么不是这个状态时呢?会执行到onSizeReady方法
@Override
public synchronized void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
...
status = Status.RUNNING;
//计算缩略图的尺寸
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
if (IS_VERBOSE_LOGGABLE) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
//加载流程
loadStatus =
engine.load(
glideContext,
model,//对应rul,图片地址
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),//默认是Object.class
transcodeClass,//默认是Drawable.class
priority,
requestOptions.getDiskCacheStrategy(),//缓存策略,默认是AUTOMATIC
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
}
复制代码
可以看到,调用了Engine的load方法,关于加载图片的加载机制,我们下一篇再讲,今天先就讲到这。
总结
这一篇主要分析Glide.with().load().into()的简单流程
- Glide类作为入口类,调用静态方法with(),实例化了Glide这个单例,取得RequestManager对象并返回
- RequestManager去管理Request请求,根据Activity或Fragment生命周期,管理request请求,包括:onStop,onStart,onDestory,pauseRequest,resumeRequests等,并可以设置加载资源要返回的资源类型,Bitmap,Drawable,Gif。通过调用load()、asBitmap()、asFile()等方法均返回一个RquestBuilder对象,将资源的请求处理移交给了RequestBuilder,实现将功能分离,模块化处理。
- RquestBuilder处理资源加载请求,调用apply()方法传入RequestOptions对象进行一些选项设置;调用transition()方法实现资源加载显示时过度动画;最后调用into()方法,去构建Rquest对象或使用Target设置过的Request对象,调用Rquest的对象方法begin()开启加载请求。
- 开启请求后的工作就移交到Request类中,加载完成后,Request调用onResourceReady()方法去判断加载结果,若加载成功,调用Target类的onReadySuccess()方法设置资源,调用RequestCoordinator中方法onRequestSuccess()执行加载成功后的资源清理工作。若加载失败,Request直接调用notifyLoadFailed()方法,将清理资源工作移交给RequestCoordinator类处理。
参考
- Glide最全解析系列文章 - 郭神基于3.x版本的。
- Android图片加载框架Glide源码解析(二)
- 深入理解Glide
- Glide使用简介及流程分析
我的CSDN
下面是我的公众号,欢迎大家关注我