一、Glide中幾個典型的類
1、RequestManagerRetriever 用于生成RequestManager的類
public class RequestManagerRetriever implements Handler.Callback {
/** The top application level RequestManager. */
private volatile RequestManager applicationManager;
private final Handler handler;
private final RequestManagerFactory factory;
@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)) {
//step 0
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
//step 1
} else if (context instanceof Activity) {
return get((Activity) context);
//step 2
} else if (context instanceof ContextWrapper
// Only unwrap a ContextWrapper if the baseContext has a non-null application context.
// Context#createPackageContext may return a Context without an Application instance,
// in which case a ContextWrapper may be used to attach one.
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
//step 3
return getApplicationManager(context);
}
@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or
// activity. However, in this case since the manager attached to the application will not
// receive lifecycle events, we must force the manager to start resumed using
// ApplicationLifecycle.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
private static final RequestManagerFactory DEFAULT_FACTORY =
new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
}
}
RequestManagerRetriever 生成了RequestManager 有兩類:
- (1) applicationManager ,該類型的RequestManager 的聲明周期和Application相同
- (2)可以感知Activity聲明周期的RequestManager,當Activity onPause之后 會停止圖片的加載
RequestManagerRetriever.get()方法有很多重載,
- 當傳入的參數(shù) Application 或者app在后臺時,會創(chuàng)建ApplicationRequestManager,聲明周期與Application同步
- 當傳入的參數(shù)是Activty、Fragment或view時,創(chuàng)建的RequestManager 會與Activity的生命周期同步。
生命周期的長短,區(qū)別就在于RequestManager構(gòu)造時傳入lifecycle對象
RequestManager是如何監(jiān)聽Activity的聲明周期的?
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
if (Util.isOnBackgroundThread()) {
return get(fragment.getContext().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
//step 1
return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible());
}
}
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
//step 2 創(chuàng)建SupportRequestManagerFragment 獲取Activity生命周期
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
//step 4 將創(chuàng)建的requestManager保存到SupportRequestManagerFragment中
current.setRequestManager(requestManager);
}
return requestManager;
}
@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) {
//step 3 創(chuàng)建一個SupportRequestManagerFragment 對象,加入到fragmentManager當中,SupportRequestManagerFragment中持有一個ActivityFragmentLifecycle 和RequestManager
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;
}
- supportFragmentGet() 生成一個SupportRequestManagerFragment 的Fragment對象,加入到FragmentManager中,這樣生成一個SupportRequestManagerFragment就有了生命周期
- SupportRequestManagerFragment 持有一個ActivityFragmentLifecycle對象,其生命周期與SupportRequestManagerFragment同步,是對外傳遞lifecycle的橋梁
- 創(chuàng)建一個RequestManager對象,并將它保存在SupportRequestManagerFragment中
- 將ActivityFragmentLifecycle生命周期對象傳遞到RequestManager中,使其可以感知Activity生命周期。
2、RequestManager
RequestManager 負責管理Request,它持有requestTracker和TargetTracker。
同一個Activity(針對非Application類型的Context) 對應(yīng)一個RequestManager,管理該Activity內(nèi)所有g(shù)lide請求。
public class RequestManager
implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
protected final Glide glide;//全局glide實例
protected final Context context;
final Lifecycle lifecycle; //感知聲明周期
//step 0 持有requestTracker和TargetTracker實例
private final RequestTracker requestTracker;//追蹤request
private final TargetTracker targetTracker = new TargetTracker();//追蹤target
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;
//step 1 感知網(wǎng)絡(luò)連接變化
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
//step 2 感知生命周期
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
//step 3 聲明周期變化
@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);
}
//step 4 構(gòu)建RequestBuilder
public RequestBuilder<Bitmap> asBitmap() {
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}
public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
}
- RequestManager 可以感知網(wǎng)絡(luò)連接變化,當網(wǎng)絡(luò)連接恢復時,可以重新開啟圖片請求,如step 1
- RequestManager 可以感知聲明周期,當生命周期變化時暫停、恢復Request,如step2 和step3
- RequestManager另一個作用是 構(gòu)造RequestBuilder對象,如step 4
3、RequestBuilder
RequestBuilder 是用于構(gòu)造Request的。
RequestBuilder 繼承與BaseRequestOptions
我們先來看一下BaseRequestOptions,它用來記錄request請求的配置信息,如展位圖、優(yōu)先級、圖形變換等
public abstract class BaseRequestOptions<T extends BaseRequestOptions<T>> implements Cloneable {
private static final int UNSET = -1;
private static final int SIZE_MULTIPLIER = 1 << 1;
private static final int DISK_CACHE_STRATEGY = 1 << 2;
private static final int PRIORITY = 1 << 3;
private static final int ERROR_PLACEHOLDER = 1 << 4;
private static final int ERROR_ID = 1 << 5;
private static final int PLACEHOLDER = 1 << 6;
private static final int PLACEHOLDER_ID = 1 << 7;
private static final int IS_CACHEABLE = 1 << 8;
private static final int OVERRIDE = 1 << 9;
private static final int SIGNATURE = 1 << 10;
private static final int TRANSFORMATION = 1 << 11;
private static final int RESOURCE_CLASS = 1 << 12;
private static final int FALLBACK = 1 << 13;
private static final int FALLBACK_ID = 1 << 14;
private static final int THEME = 1 << 15;
private static final int TRANSFORMATION_ALLOWED = 1 << 16;
private static final int TRANSFORMATION_REQUIRED = 1 << 17;
private static final int USE_UNLIMITED_SOURCE_GENERATORS_POOL = 1 << 18;
private static final int ONLY_RETRIEVE_FROM_CACHE = 1 << 19;
private static final int USE_ANIMATION_POOL = 1 << 20;
//BaseRequestOptions request請求的參數(shù)配置信息
//step 0 fields 32bit整型,用特定的bit位 表示是否設(shè)置了某項配置.
private int fields;
//step 1 用下面的屬性 來記錄具體的配置信息
private float sizeMultiplier = 1f; //放縮系數(shù)
//緩存策略
@NonNull private DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;
//優(yōu)先級
@NonNull private Priority priority = Priority.NORMAL;
//加載失敗的占位圖Drawable
@Nullable private Drawable errorPlaceholder;
//加載失敗的占位圖資源ID
private int errorId;
@Nullable private Drawable placeholderDrawable;
private int placeholderId;
private boolean isCacheable = true;
//指定寬高
private int overrideHeight = UNSET;
private int overrideWidth = UNSET;
//請求對應(yīng)的唯一的key
@NonNull private Key signature = EmptySignature.obtain();
private boolean isTransformationRequired;
private boolean isTransformationAllowed = true;
@Nullable private Drawable fallbackDrawable;
private int fallbackId;
@NonNull private Options options = new Options();
//圖形變換數(shù)組
@NonNull
private Map<Class<?>, Transformation<?>> transformations = new CachedHashCodeArrayMap<>();
//最終請求的資源類型,如Drawable、bitmap、gifDrawable等
@NonNull private Class<?> resourceClass = Object.class;
private boolean isLocked;
@Nullable private Resources.Theme theme;
private boolean isAutoCloneEnabled;
private boolean useUnlimitedSourceGeneratorsPool;
private boolean onlyRetrieveFromCache;
private boolean isScaleOnlyOrNoTransform = true;
private boolean useAnimationPool;
}
BaseRequestOptions 設(shè)置配置項時需要同時設(shè)置配置項和fileds字段(表示設(shè)置了某項配置)
public T diskCacheStrategy(@NonNull DiskCacheStrategy strategy) {
if (isAutoCloneEnabled) {
return clone().diskCacheStrategy(strategy);
}
this.diskCacheStrategy = Preconditions.checkNotNull(strategy);
fields |= DISK_CACHE_STRATEGY;
return selfOrThrowIfLocked();
}
RequestBuilder 繼承自BaseRequestOptions
使用來構(gòu)造Request的。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.DATA)
.priority(Priority.LOW)
.skipMemoryCache(true);
//step 0 首先 RequestBuilder 是用來構(gòu)建請求的, 它繼承自BaseRequestOptions,承載了眾多的加載配置項
private final Context context;
//step 1 持有RequestManager、全局的Glide和GlideContext
private final RequestManager requestManager;
private final Glide glide;
private final GlideContext glideContext;
//step 2 補充了額外的配置選項
//指定待加載的資源(數(shù)據(jù)源),可以是string,URL、URI、ReqsourceID、File等
@Nullable private Object model;
//是否設(shè)置過model
private boolean isModelSet;
//指最終輸出的資源類型,如Drawable、bitmap等
private final Class<TranscodeType> transcodeClass;
//指定動畫過渡效果
private TransitionOptions<?, ? super TranscodeType> transitionOptions;
//制定了Requestlistner
@Nullable private List<RequestListener<TranscodeType>> requestListeners;
@Nullable private RequestBuilder<TranscodeType> thumbnailBuilder;
@Nullable private RequestBuilder<TranscodeType> errorBuilder;
@Nullable private Float thumbSizeMultiplier;
private boolean isDefaultTransitionOptionsSet = true;
private boolean isThumbnailBuilt;
//step 3 load方法,設(shè)置數(shù)據(jù)源
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
//step 4 into()方法傳入Target
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null, Executors.mainThreadExecutor());
}
@Synthetic
<Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
Executor callbackExecutor) {
return into(target, targetListener, /*options=*/ this, callbackExecutor);
}
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request request = buildRequest(target, targetListener, options, callbackExecutor);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!Preconditions.checkNotNull(previous).isRunning()) {
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
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());
}
}
a、它持有RequestManager、全局的Glide和GlideContext
b、除了基本的配置項之外,補充了額外的配置選項,如
- model數(shù)據(jù)源、
- transcodeClass 最終的要獲取的資源類型,如Drawable、bitmap等
- transitionOptions 動畫過渡效果
- requestListeners 請求監(jiān)聽器
c、RequestBuilder的一個重要方法load 用于指定數(shù)據(jù)源
4、into(target) 方法,用于生成Request,并將結(jié)果傳遞給Target
4、Target
a、Target是一個interface接口,繼承自LifecycleListener
public interface Target<R> extends LifecycleListener {
//開始加載圖片,顯示placheholder
void onLoadStarted(@Nullable Drawable placeholder);
//加載失敗,顯示errorDrawable
void onLoadFailed(@Nullable Drawable errorDrawable);
//request取消,加載fallback Drawable
void onLoadCleared(@Nullable Drawable placeholder);
//下載成功,回調(diào)onResourceReady
void onResourceReady(@NonNull R resource, @Nullable Transition<? super R> transition);
//請求圖片的尺寸
void getSize(@NonNull SizeReadyCallback cb);
void removeCallback(@NonNull SizeReadyCallback cb);
//保存request對象
void setRequest(@Nullable Request request);
Request getRequest();
}
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
Target 具有LifecycleListener的能力,可以感知生命周期(onStrat、onStop、onDestroy)
同時具有以下能力
- onLoadStarted,開始加載圖片,顯示placheholder
- onLoadFailed,加載失敗,顯示errorDrawable
- request取消,加載fallback Drawable
- onResourceRead,下載成功,將resource資源回調(diào)給Target
- getSize,請求圖片尺寸
- setRequest(),getRequest() 持有Request對象
b、BaseTarget
BaseTarget 持有request屬性,實現(xiàn)了setRequest、getRequest方法
public abstract class BaseTarget<Z> implements Target<Z> {
private Request request;
@Override
public void setRequest(@Nullable Request request) {
this.request = request;
}
@Override
@Nullable
public Request getRequest() {
return request;
}
//其他父類方法
...
}
c、ViewTarget
ViewTarget 集成自BaseTarget,持有一個View對象。
- Request 保存在了view對象的tag中
- 實現(xiàn)了getSize() ,通過SizeDeterminer 計算Bitmap 最終的尺寸,再通過SizeReadyCallback進行回調(diào).
- 注冊了View的OnAttachStateChangeListener,onViewAttachedToWindow時resumeRequest,onViewDetachedFromWindow時 pauseRequest
public abstract class ViewTarget<T extends View, Z> extends BaseTarget<Z> {
//step 0 ViewTarget 持有一個View
protected final T view;
private final SizeDeterminer sizeDeterminer;
@Nullable private OnAttachStateChangeListener attachStateListener;
public ViewTarget(@NonNull T view) {
this.view = Preconditions.checkNotNull(view);
sizeDeterminer = new SizeDeterminer(view);
}
//step 2 實現(xiàn)了計算ImageView尺寸的方式,通過sizeDeterminer計算,計算完成通過SizeReadyCallback 回傳
public void getSize(@NonNull SizeReadyCallback cb) {
sizeDeterminer.getSize(cb);
}
@Override
public void setRequest(@Nullable Request request) {
setTag(request);
}
//step 1 request 保存在了View的Tag上
private void setTag(@Nullable Object tag) {
isTagUsedAtLeastOnce = true;
view.setTag(tagId, tag);
}
//step 2 監(jiān)測View的attach, attach時 resumeRequest,dettach時pauseRequest
public final ViewTarget<T, Z> clearOnDetach() {
if (attachStateListener != null) {
return this;
}
attachStateListener =
new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
resumeMyRequest();
}
@Override
public void onViewDetachedFromWindow(View v) {
pauseMyRequest();
}
};
maybeAddAttachStateListener();
return this;
}
}
d、 ImageViewTarget
ImageViewTarget 繼承自ViewTarget,重點實現(xiàn)的是Animatable動畫相關(guān)的操作
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
@Nullable private Animatable animatable;
//step 0 實現(xiàn)了Transition.ViewAdapter
public Drawable getCurrentDrawable() {
return view.getDrawable();
}
public void setDrawable(Drawable drawable) {
view.setImageDrawable(drawable);
}
//step 1 實現(xiàn)了onLoadFailed()、onLoadFailed()、onLoadCleared(), 顯示placheHolder、errorDrawable、fallbackDrawable
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
setDrawable(placeholder);
}
public void onLoadFailed(@Nullable Drawable errorDrawable) {
super.onLoadFailed(errorDrawable);
setDrawable(errorDrawable);
}
public void onLoadCleared(@Nullable Drawable placeholder) {
super.onLoadCleared(placeholder);
if (animatable != null) {
animatable.stop();
}
setDrawable(placeholder);
}
//實現(xiàn)了onResourceReady 資源備妥后 顯示動畫
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
//step 2 onStart()啟動動畫,onStop() 通知動畫
@Override
public void onStart() {
if (animatable != null) {
animatable.start();
}
}
@Override
public void onStop() {
if (animatable != null) {
animatable.stop();
}
}
protected abstract void setResource(@Nullable Z resource);
}
- 實現(xiàn)了Transition.ViewAdapter 接口
Transition.ViewAdapter
public interface Transition<R> {
interface ViewAdapter {
View getView();
Drawable getCurrentDrawable();
void setDrawable(Drawable drawable);
}
}
實現(xiàn)了onLoadFailed()、onLoadFailed()、onLoadCleared() 方法,分別顯示placheHolder,errorDrawable、fallbackDrawable
實現(xiàn)onResourceReady 動畫顯示Drawable
生命周期onStart()、onStop() 啟動或停止動畫
setResource() 是個虛方法,留給子類實現(xiàn)
e、BitmapImageViewTarget
BitmapImageViewTarget 繼承自ImageViewTarget,指定了Resource的類型為Bitmap,實現(xiàn)了setResource方法
public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
// Public API.
@SuppressWarnings("WeakerAccess")
public BitmapImageViewTarget(ImageView view) {
super(view);
}
/**
*
* @param resource The bitmap to display.
*/
@Override
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
}
f、DrawableImageViewTarget
DrawableImageViewTarget 繼承自ImageViewTarget,指定了Resource類型為Drawable,并實現(xiàn)了setResource方法
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
7、Request
Request 實現(xiàn)將resource加載到Target中,是一個接口,具體實現(xiàn)由子類實現(xiàn)。
//一個Request 實現(xiàn)如何加載resource到Target中
public interface Request {
//開始異步加載
void begin();
//停止加載,釋放資環(huán)
void clear();
void pause();
boolean isRunning();
boolean isComplete();
boolean isCleared();
boolean isAnyResourceSet();
boolean isEquivalentTo(Request other);
}
SingleRequest 是Request的實現(xiàn)類,SingleRequest內(nèi)部定義了一個Status枚舉,標記Request請求所處的階段
public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback {
private enum Status {
/** Created but not yet running. */
PENDING,
/** In the process of fetching media. */
RUNNING,
/** Waiting for a callback given to the Target to be called to determine target dimensions. */
WAITING_FOR_SIZE,
/** Finished loading media successfully. */
COMPLETE,
/** Failed to load media, may be restarted. */
FAILED,
/** Cleared by the user with a placeholder set, may be restarted. */
CLEARED,
}
}
- PENDING :Request剛創(chuàng)建,尚未執(zhí)行
- WAITING_FOR_SIZE:等待獲取Target的尺寸,獲取成功后,會通過callback 傳遞到Request的onSizeReady()
- RUNNING:Target尺寸確定了之后,進入Running狀態(tài),開始加載Resource
- COMPLETE:加載成功,status切換為成功狀態(tài)
- FAILED:加載失敗狀態(tài)
- CLEARED:資源被清除
所以常規(guī)的狀態(tài)流應(yīng)該是:
PENDING->WAITING_FOR_SIZE->RUNNING->COMPLETE
二、glide使用三板斧
Glide.with(iv_glide).load(url).into(iv_glide)
1、with 操作符返回一個RequestManager
Glide.with(context) 返回一個RequestManager
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
- step == 0 Glide.get()會進行Glide的全局初始化
- step == 1 getRetriever() 獲取以一個RequestManagerRetriever對象
- step == 2 RequestManagerRetriever.get() 返回一個RequestManger對象
glide.with()可以傳入不同的context,返回不同的RequestManager
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)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper
// Only unwrap a ContextWrapper if the baseContext has a non-null application context.
// Context#createPackageContext may return a Context without an Application instance,
// in which case a ContextWrapper may be used to attach one.
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
以傳入FragmentActivity為例子,
- 當前處于后臺時,會創(chuàng)建給ApplciationRequestManager
- 當處于前臺時,會創(chuàng)建一個無界面的SupportRequestManagerFragment 加入到FragmentManager中,SupportRequestManagerFragment中維護一個ActivityFragmentLifecycle,與Activity生命周期同步,此lifeCycle會傳遞到Request中,感知Activity聲明周期。
@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));
}
}
@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;
}
2、load 操作符返回RequestBuilder
RequestManager.load方法返回RequestBuilder對象,并指定了數(shù)據(jù)源(如圖片加載鏈接)
RequestManager.hava
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
- load默認是產(chǎn)生RequestBuilder<Drawable>,指定輸出的resource類型是Drawable
- asBitmap、asGif 方法可以指定資源類型為Bitmap或者GifDrawable
public RequestBuilder<Bitmap> asBitmap() {
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}
public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}
- RequestBuilder 鏈式調(diào)用可以指定Request的各種配置和屬性
Glide.with(iv_glide)
.load(url)
.placeholder(R.drawable.ic_launcher_background)
.error(R.drawable.ic_launcher_foreground)
.fallback(R.drawable.ic_launcher_foreground)
.transform(RoundTransformation(50), RotateTransformation(90F))
.transition(DrawableTransitionOptions.withCrossFade(1000 * 10))
.into(iv_glide)
3、into操作符
into操作符傳入一個ImageView,觸發(fā)圖片獲取和加載
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
//step 0 生成一個BitMapImageViewTarget 或者DrawableImageViewTarget
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
//step 1 構(gòu)造一個SingleRequest
Request request = buildRequest(target, targetListener, options, callbackExecutor);
requestManager.clear(target);
target.setRequest(request);
//step 2 通過requestManager 追蹤,啟動 SingleRequest的執(zhí)行
requestManager.track(target, request);
return target;
}
- 首先通過傳入的ImageView 構(gòu)造了,根據(jù)TranscodeType 生成了一個ImageViewTarget
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(
@NonNull ImageView view, @NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
}
- 通過上一步生成的ImageViewTarget,構(gòu)造SingleRequest
- 將SingleRequest 傳入requestManager,觸發(fā)圖片的加載過程。
requestManager.track(target, request);
##RequestManager.java
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
RequestTracker.java
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
至此Glide操作的三板斧執(zhí)行完畢
三、Reqeust 請求是如何執(zhí)行的
3.1、RequestBuilder.into()方式是真正圖片加載的入口
RequestBuilder.java
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view){
//step 0 產(chǎn)生ImageViewTarget
target = glideContext.buildImageViewTarget(view, transcodeClass)
//step 1 生成一個SingleRequest對象
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//先取消target上的圖片加載(如果有的話)
requestManager.clear(target);
target.setRequest(request);
//step 2 將target、request加入到requestManager
requestManager.track(target, request);
}
#RequestManager.java
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
#RequestTracker.java
public void runRequest(@NonNull Request request) {
//step 3 將request加入到requests隊列
requests.add(request);
if (!isPaused) { //RequestTracker不是pause狀態(tài),則直接啟動request
request.begin();
} else { //RequestTracker處于pause狀態(tài),則將request加入到pendingRequest待執(zhí)行Request隊列
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
代碼的調(diào)用流程為
RequestBuilder.into()->
RequestMananger.track()->
requestTracker.runRequest()->
request.begin()
3.2、request.begin()
request 實際SingleRequest實例
#SingleRequest.java
public void begin() {
//step 0 model 為空 -> onLoadFailed
if (model == null) {
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
// 正在執(zhí)行的Request不允許再次執(zhí)行
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
//執(zhí)行完成,回調(diào)onResourceReady 回傳圖片文件
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
// step 1 最初status狀態(tài) 是WAITING_FOR_SIZE,等待獲取目標圖片大小
status = Status.WAITING_FOR_SIZE;
//如果指定了overrideWidth和overrideHeight 則直接使用回調(diào)onSizeReady()
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
//用于未指定圖片大小,則交由target取獲取目標圖片的大小(對于ImageViewTarget size一般是ImageViewK控件的尺寸)
target.getSize(this);
}
//step 2 回調(diào)onLoadingStarted
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
}
@Override
public void onSizeReady(int width, int height) {
//step 3 獲取target尺寸成功,調(diào)用Engine.load開始加載圖片
status = Status.RUNNING;
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.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this,
callbackExecutor);
}
//step 4
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
...
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
notifyLoadSuccess();
}
- step 0
可以看到判斷model變量為null,就回調(diào)onLoadFailed方法,這個方法就會設(shè)置我們配置的error placeholder資源。這里的model變量就是我們通過load(myUrl)方法傳入的圖片地址。
step 1
判斷overrideWidth, overrideHeight是否可用。
如果設(shè)置了override(int width, int height) ,直接處理onSizeReady方法邏輯;如果沒有設(shè)置override,Glide就會等到系統(tǒng)計算完組件(一般是ImageView組件)寬高后再回調(diào)onSizeReady。這兩種情況最后都會調(diào)用onSizeReady方法。step 2
已經(jīng)開始了圖片的加載,回調(diào)設(shè)置placeholderDrawable,顯示placeHolder占位圖。step 3 獲取圖片尺寸成功,engine.load 開始圖片的加載過程
step 4
image加載完成回調(diào)。這里是加載、縮放、轉(zhuǎn)換之后的數(shù)據(jù),可直接用于UI顯示。
3.3、engine.load()
#Engine.java
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) {
//(1)生成緩存key
EngineKey key =
keyFactory.buildKey(
model,
signature,
width,
height,
transformations,
resourceClass,
transcodeClass,
options);
//(2)從內(nèi)存緩存中匹配目標圖片資源(又細分為activeResources和cache)
memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
//(4) 內(nèi)存緩存未命中,則嘗試從磁盤緩存或者網(wǎng)絡(luò)加載圖片
return waitForExistingOrStartNewJob(
glideContext,
model,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
options,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache,
cb,
callbackExecutor,
key,
startTime);
}
}
//(3)若內(nèi)存緩存命中,則直接返回onResourceReady
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
}
默認情況下,Glide 會在開始一個新的圖片請求之前檢查以下多級的緩存:
活動資源 (Active Resources) - 正在顯示的資源
內(nèi)存緩存 (Memory cache) - 顯示過的資源
資源類型(Resource) - 被解碼、轉(zhuǎn)換后的資源
數(shù)據(jù)來源 (Data) - 源文件(未處理過)資源
也就是內(nèi)存緩存+磁盤緩存。
首先engine.load方法 首先會生成EngineKey,然嘗試從內(nèi)存中檢索緩存,如注釋(2)
先后從Active Resources和Memory cache中檢索緩存,若命中,則直接直接回調(diào)onResourceReady,如注釋(3)
@Nullable
private EngineResource<?> loadFromMemory(
EngineKey key, boolean isMemoryCacheable, long startTime) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> active = loadFromActiveResources(key);
if (active != null) {
return active;
}
EngineResource<?> cached = loadFromCache(key);
if (cached != null) {
return cached;
}
return null;
}
若內(nèi)存緩存未命中,則嘗試啟動解碼任務(wù)開始解碼圖片,如注釋(4)
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) {
//創(chuàng)建EngineJob,EngineJob是一個Runnable
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//創(chuàng)建DecodeJob
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);
//啟動decodeJob
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
DecodeJob是整個流程中的重點,我們重點看EngineJob做了哪些事情
//執(zhí)行EngineJob的start方法
//start方法就是根據(jù)diskCacheStrategy策略獲取一個executor來執(zhí)行DecodeJob
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
//這里根據(jù)緩存策略,決定使用哪個Executor。默認情況返回diskCacheExecutor。
//共三種執(zhí)行器:diskCacheExecutor、sourceExecutor、sourceUnlimitedExecutor對應(yīng)文章前面給出的流程圖。
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
//當然,DecodeJob實現(xiàn)了Runnable接口。直接來看它的run方法。
@Override
public void run() {
runWrapped();//看這里!
}
//接著看runWrapped方法。
//RunReason是一個枚舉,默認值為INITIALIZE。區(qū)分任務(wù)目的。
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);
}
}
//獲取任務(wù)執(zhí)行階段:初始化、讀取轉(zhuǎn)換后的緩存、讀取原文件緩存、原文件加載、結(jié)束狀態(tài)。
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:
// Skip loading from source if the user opted to only retrieve the resource from cache.
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
//根據(jù)上一個方法確定的stage,創(chuàng)建對應(yīng)的Generator(可把它簡單理解成資源加載器)
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
//從轉(zhuǎn)換后的緩存中讀取文件
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
//從原文件緩存中讀取文件
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
//沒有緩存,重新加載資源(比如:網(wǎng)絡(luò)圖片、本地文件)
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
//這里開始加載執(zhí)行
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
//這里Generator.startNext()方法中就是加載過程,如果成功加載則返回true并跳出循環(huán),否則切換Generator繼續(xù)執(zhí)行。
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
//如果任務(wù)執(zhí)行到去加載資源(也就是沒有命中磁盤緩存),且切換任務(wù)執(zhí)行環(huán)境
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
// Otherwise a generator started a new load and we expect to be called back in
// onDataFetcherReady.
}
@Override
public void reschedule() {
//更改執(zhí)行目標為:SOURCE服務(wù)。當然也只有在stage == Stage.SOURCE的情況下會被調(diào)用。
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);//這里callback正是EngineJob。
}
//代碼跟進EngineJob類中,可以看到實現(xiàn)方法。
@Override
public void reschedule(DecodeJob<?> job) {
// 可以看到,這里獲取的SourceExecutor來執(zhí)行decodeJob。
//也就巧妙地將此decodeJob任務(wù)從cacheExecutor切換到了SourceExecutor,這樣分工協(xié)作更加高效。
getActiveSourceExecutor().execute(job);
}
從最開始沒有命中內(nèi)存緩存開始,然后執(zhí)行Engine的start方法,默認情況會獲取到cacheExecutor執(zhí)行器來執(zhí)行decodeJob任務(wù);繼續(xù)decodeJob的run方法,因為RunReason==INITIALIZE,接著獲取stage,默認會返回Stage.RESOURCE_CACHE,這時通過getNextGenerator就返回了ResourceCacheGenerator加載器,緊接著就是調(diào)用 ResourceCacheGenerator的startNext方法 ,從轉(zhuǎn)換后的緩存中讀取已緩存的資源,如果命中則結(jié)束任務(wù)并回調(diào)結(jié)果,反之,任務(wù)切換到DataCacheGenerator加載器繼續(xù)執(zhí)行,若還是未命中,則切換到SourceGenerator加載器(第一次加載,由于沒有任何緩存,就會走到這里),這時會通過任務(wù)調(diào)度,將線程運行環(huán)境切換到 SourceExecutor執(zhí)行器來執(zhí)行,最后,待SourceGenerator加載完成后結(jié)束任務(wù),回調(diào)結(jié)果,流程結(jié)束。
