Glide基本用法
Glide.with(context).load(obj).into(imageView)
with()源码解析
public static RequestManager with(Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(View view) {
return getRetriever(view.getContext()).get(view);
}
- 会根据上面传入的参数不一样,然后调用
getRetriever()
,Glide.get(Context)
主要是检查并初始化单例对象Glide,并且判断AndroidManifest
有没有配置module或者自己新建一个类添加注解GlideModule
,如果有会反射获取会注册Glide中的组件和参数完成后,调用getRequestManagerRetriever()
返回一个RequestManagerRetriever
对象
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
- 返回的
RequestManagerRetriever
对象又调用了get(T t)
方法,这也是一个重载函数,共同特点就是如果是非主线程调用Glide统一当做Application
来处理,分类看一下
Context
对象会根据Context
对应的实例调用不同的方法。
其他方法共同点都是创建一个隐藏的Fragment
如果实参是V4包中Activity
或Fragment
会创建SupportRequestManagerFragment
对象
如果实参不是V4包中的就返回RequestManagerFragment
对象
RequestManager
和Fragment
进行一个生命周期的绑定,如果当页面被隐藏,图片加载请求也会相应取消,从而更加节约性能。
最终返回的是一个RequestManager
对象。
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);
}
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());
// The view might be somewhere else, like a service.
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
// Support Fragments.
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);
}
- 综上分析,
with()
就返回一个RequestManager
对象,然后根据传入的参数来绑定图片加载的生命周期。
Glide如何绑定生命周期
- 下面来看看创建的
Fragment
是如何和RequestManager
进行生命周期绑定,由上分析可知我们会得到一个Fragment
对象,在Fragment构造函数中会创建一个ActivityFragmentLifecycle
,可以看到在各个生命周期函数都会调用lifecycle
的函数进行监听。
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@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();
}
- 再来看看
RequestManger
的创建过程,current
参数就是上面创建好的Fragment
对象,通过getGlideLifecycle
方法获取到刚才在构造函数中创造的ActivityFragmentLifecycle
的对象,从而传递给通过工厂模式建立的RequestManager
。
private RequestManager supportFragmentGet(Context context, FragmentManager fm,
Fragment parentHint) {
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager =
factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
-
RequestManager
自己实现了LifecycleListener
的监听器接口,在构造函数中,在从上面Fragment
传递过来的ActivityFragmentLifecycle
对象添加监听器。在onStart()
中启动请求,在onStop()
中暂停请求,在onDestroy()
做一些清理工作。
public class RequestManager implements LifecycleListener {
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory) {
......
connectivityMonitor =
factory.build(context, new RequestManagerConnectivityListener(requestTracker));
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
}
......
@Override
public void onStart() {
resumeRequests();
targetTracker.onStart();
}
@Override
public void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public 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);
}
}
- 监听器也注册了,那么进入
ActivityFragmentLifecycle
内部看看,发现在内部的生命周期方法中会调用监听器对应的方法。
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();
}
}
- 经过上面的分析发现整个过程就理顺了,先创建一个
Fragment
对象并在构造函数中创建Lifecycle
对象
,在通过工厂模式创建RequestManager
的时候会把Lifecycle
对象传递进去。
RequestManger
则会在构造函数处会将接受的Lifecycle
添加监听器,RequestManager
自身实现了LifecycleListener
并在实现的接口方法中根据生命周期方法来启动和暂停请求。
Lifecycle
对象在添加监听器后,会在生命周期方法中回调监听器对应的方法。
因此当Fragment
会在生命周期方法中调用Lifecycle
对应的生命周期方法,最终也就是在调用RequestManger
中的生命周期方法,因此实现了请求和生命周期的绑定,从而可以根据生命周期来启动和暂停请求。
load()源码解析
- 通过
with()
返回RequestManager
对象再调用load()
方法,如果没有调用asxxx()
方法,都默认调用asDrawable()
方法,最后创建返回了一个RequestBuilder<Drawable>
对象。
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
- 在
RequestBuilder
对象中,根据参数的不同,load()
也有很多方法的重载,如下所示,发现共同点所有方法都会调用loadGeneric(T t)
方法,下面来看看这个方法的实现。
public RequestBuilder<TranscodeType> load(@Nullable Object model) {
return loadGeneric(model);
}
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
return loadGeneric(uri);
}
public RequestBuilder<TranscodeType> load(@Nullable File file) {
return loadGeneric(file);
}
public RequestBuilder<TranscodeType> load(@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) {
return loadGeneric(model).apply(signatureOf(new ObjectKey(UUID.randomUUID().toString()))
.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true));
}
-
loadGeneric(Object model)
方法很简单,将传入的model
赋值给RequestBuilder
的成员变量,并设置赋值的标志位为true。
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
- 综上可以看出,经过
load()
方法会创建并返回一个RequestBuilder
方法,并把load()
中的参数图片源传递进去。
into()源码解析
- 上面的
load()
方法返回了一个RequestBuilder
方法,然后调用其中的into()
,通过下面的into()
进行,首先会进行是否有图片数据源和ScaleType
的判断,会根据我们XML里面设置的ScaleType
会做相应的设置,所以如果我们xml已经设置了,就不要在使用Glide的时候再设置一遍,最后调用另外一个重载的into()
方法。
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
if (requestOptions.isLocked()) {
requestOptions = requestOptions.clone();
}
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions.optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions.optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions.optionalFitCenter();
break;
case FIT_XY:
requestOptions.optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(context.buildImageViewTarget(view, transcodeClass));
}
- 上述只是简单逻辑判断和设置,into方法也有两个重载,另外一个就是最后一行调用的
into(Y target)
,而这个参数是通过context.buildImageViewTarget(view, transcodeClass)
来构造的实参。
而传入clazz参数就和我们调用asXXX()
相关:
如果调用的是asBitmap
传入的是Bitmap.class
就返回BitmapImageViewTarget
对象。
如果调用的是asDrawable
传入的是Drawable.class
,返回DrawableImageViewTarget
对象。
如果调用的是asGif
传入的是Drawable
的子类GifDrawable
,也返回DrawableImageViewTarget
对象。
如果调用的是as(Class c)
,实参不是Bitmap
或者不是Drawable
的子类就会抛异常。
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
- 下面来具体看看调用
into(Y traget)
方法实现,先通过buildRequest
方法构建了一个Request
对象,先判断target
是之前已经绑定了请求,如果旧请求和新请求一样且处于请求完成或者正在请求状态就直接复用旧请求。如果不复用,就RequestManager
先移除和旧请求绑定的target
对象,Target
再重新和Request
对象进行一个绑定,调用requestManager.track(target, request)
再加入请求队列,开启请求,最后返回经过处理的traget
对象。
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
requestOptions.lock();
Request request = buildRequest(target);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& (Preconditions.checkNotNull(previous).isComplete()
|| Preconditions.checkNotNull(previous).isRunning())) {
request.recycle();
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
- 通过上面分析可知
into
方法中最关键的两处代码分别是buildRequest
和requestManager.track
,一个是构建请求,一个是执行请求,搞懂了这两处代码基本就搞懂了Glide
请求图片的流程。
Request request = buildRequest(target);
requestManager.track(target, request);
- 下面来看看
buildRequest
内部又调用了buildRequestRecursive
方法,如下所示代码省略号部分是在处理缩略图,如果对这块不关注的话,可以看到最后调用了obtainRequest
方法来返回一个Request
对象。
private Request buildRequest(Target<TranscodeType> target) {
return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight());
}
private Request buildRequestRecursive(Target<TranscodeType> target,
@Nullable ThumbnailRequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority, int overrideWidth, int overrideHeight) {
......
return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
overrideWidth, overrideHeight);
}
- 再深入进入
obtainRequest
方法中看看,里面又调用了SingleReuqest.obtain
方法,一环嵌套一环。
private Request obtainRequest(Target<TranscodeType> target,
RequestOptions requestOptions, RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,
int overrideWidth, int overrideHeight) {
requestOptions.lock();
return SingleRequest.obtain(
context,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
requestListener,
requestCoordinator,
context.getEngine(),
transitionOptions.getTransitionFactory());
}
- 在这个方法里面可以看到创建了一个
SingleRequest
对象,并进行了初始化,初始化主要是进行成员参数的一个赋值操作。至此我们弄清楚了Glide为我们构建了一个SingleRequest
的请求对象,下面来看看是请求启动的过程。
public static <R> SingleRequest<R> obtain(
GlideContext glideContext,
Object model,
Class<R> transcodeClass,
RequestOptions requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory) {
@SuppressWarnings("unchecked") SingleRequest<R> request =
(SingleRequest<R>) POOL.acquire();
if (request == null) {
request = new SingleRequest<>();
}
request.init(
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
requestListener,
requestCoordinator,
engine,
animationFactory);
return request;
}
- 通过对
requestManager.track(target, request);
的追踪来看看,请求是如何被启动的。track
方法中调用了runRquest
方法,这就是启动Request的开关。
void track(Target<?> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
- 在
runRequest
中请求会加入请求队列,isPaused
,这个状态是根据生命周期挂钩的,如果处于暂停状态,就先将请求放入待处理队列;如果不是可以调用begin
方法开始请求,这里的request
就是我们上面创建并返回的SimpleRequest
对象。
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
- 下面来看看
SimpleRquest
中的begin
方法,首先判断model
是否为空,model
就是我们load
方法中传入的对象,如果为空,就看有没有设置好的错误图片可以使用,如果有就显示错误图片,再判断是否有占位图,如果有就显示占位图,注意如果如果既设置了占位图又设置了占位图,优先显示占位图。
如果请求已经在运行了,会抛出异常,因为不可重复启动请求。
如果请求已经完成了,这时候又发送了一个相同的请求加载到一样的View中,就会取最新一次请求获取的资源和大小,让View重新加载一遍,就不重新进行请求了,节约资源。
如果以上条件都符合,是一个新的合法请求,会先判断加载的长宽是否合法,如果合法会调用onSizeReady
方法,如果不合法会经过计算也会调用onSizeReady
方法。
还有需要注意下面调用的onLoadStarted
只是设置了占位图了,并不是真正开启来请求的加载。
public void begin() {
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
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 (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
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));
}
}
-
onSizeReady
方法修改status
为RUNNING
的状态,其次获取长度和宽度,通过传入所有参数到engine.load
方法,开始加载图片。
egine
是Engine
的对象,专门负责负责启动加载过程并管理正在显示的图片资源和已经缓存图片资源。
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
loadStatus = engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getOnlyRetrieveFromCache(),
this);
}
- 在
load
方法中主要分别创建了EngineJob
和DecodeJob
的对象
EngineJob
负责管理加载回调函数,可以添加和移除回调函数,并且当加载完成之后会调用。
DecodeJob
负责缓存和网络请求资源。
public <R> LoadStatus load(...) {
......
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,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
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);
}
- 来看一下
engineJob.start(decodeJob)
中的代码, 会调用父类ThreadPoolExecutor
的的execute
的方法,传入的是实现了Runnable
接口的类,decodeJob
实现了Runnable
接口,因此调用是decodeJob
中的run方法
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
public void execute(Runnable command) {
if (executeSynchronously) {
command.run();
} else {
super.execute(command);
}
- 看一下
decodeJob
中的run
方法,发现主要调用的是runWrapped
方法
public void run() {
TraceCompat.beginSection("DecodeJob#run");
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (RuntimeException e) {
.....
}
} finally {
......
}
}
-
runWrapped
方法中有四种类型,刚开始肯定是INITIALIZE
,所以分别看一下这个三个方法
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);
}
}
- 第一个方法
getNextStage(Stage.INITIALIZE)
,getNextStage
中如果是INITIALIZE
,会调用decodeCachedResource
函数根据返回的bool值来判断返回的状态,由于diskCacheStrategy
是DiskCacheStrategy
的对象,decodeCachedResource
固定返回true,因此将会返回RESOURCE_CACHE
状态。
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 onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
public boolean decodeCachedResource() {
return true;
}
- 当调用完
getNextStage(Stage.INITIALIZE)
方法后,stage
的状态变成了RESOURCE_CACHE
,接下来调用getNextGenerator
方法,也是根据stage
的判断生成不同的对象,根据当前stage
为RESOURCE_CACHE
状态创建了ResourceCacheGenerator
对象
这三个Generator
分别代表的含义是:
-
ResourceCacheGenerator
:表示从已经处理过的缓存获取数据,比如缩略图,进行放大缩小等图片处理
-
DATA_CACHE
: 表示从原始缓存加载数据。
-
SOURCE
: 表示从数据源加载数据
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);
}
}
- 上面知道了
currentGenerator
被赋值为ResourceCacheGenerator
的对象,下面执行第三步runGenerators()
,会发现进去了一个while循环,正常情况下前半部分条件肯定是满足的,关键后半部分
currentGenerator.startNext()
。
在ResourceCacheGenerator中``startNext
主要判断的为是否缓存了处理过的图片,如果第一次加载肯定不满足,就接着调用上面的那两个方法,stage
会再变成DATA_CACHE
,currentGenerator
被赋值为DataCacheGenerator
的对象,继续判断是否有原始缓存,如果没有stage
状态变成SOURCE
, currentGenerator
被赋值为SourceGenerator
的对象,直接调用reschedule
方法,然后return退出。
所以加载图片的顺序是处理过的缓存图片-原始缓存图片-从数据源获取图片,如网络加载。
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
- 在
reschedule
方法中,runReason
变成了SWITCH_TO_SOURCE_SERVICE
,通过上面DecodeJob
的函数callback就是传入的engineJob
,reschedule
方法就是又重新调用了一遍executor.execute(decodeJob)
,也就执行了run
方法,又回到了runWrapped
方法中,不过这时的runReason
已经是SWITCH_TO_SOURCE_SERVICE
,所以直接执行runGenerators
方法,即开始执行
SourceGenerator
的startNext
方法
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
}
- 下面来看看
SourceGenerator
中的startNext
方法
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
网友评论