Glide源码学习-with,load,into
with主线:
1 给我们New了一个glide对象
2 创建一个空的fragment 并且绑定fragment
3 把生命周期传导出去
load主线:初始化url或byte等,注册机注册,返回RequestBuilder对象
into:除了生命周期 所有的的功能都是into做的
相当复杂,网络请求、线程切换、数据渲染、不同尺寸图片等
一、with
根据 with 源码分析,我们知道,Glide.with(Activity) 主要做了线程池 + 缓存 + 请求管理与生命周期绑定+其它配置初始化的构建,内部的代码很庞大
与with源码相关的类大概有以下几个:
Glide:主要做一些 init 工作,比如缓存,线程池,复用池的构建等等。
RequestManagerRetriever:主要是获得一个 RequestManager 请求管理类,然后绑定一个 Fragment 。
SupportRequestManagerFragment :用于管理请求的生命周期。
RequestManager:主要用于对请求的管理封装。
Glide.with(this).load(url).into(iv_image1);
点击with会跳转到Glide这个类中:会有一些重载方法
@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.getContext()).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);
}
但是实际上我们常用的也就是Activity,Fragment, Context 这 3 种形式,然后点击getRetriever(activity)这个方法,查看具体实现:
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
点击get方法,是返回了一个Gilde的单例类:
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
这里面使用了单例双重检测模式(DCL),双重锁定,保证多线程下线程安全
再点击 checkAndInitializeGlide(context, annotationGeneratedModule)这个方法:
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException(
"You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
//是否初始化的标志
isInitializing = true;
//开始进行初始化
initializeGlide(context, generatedAppGlideModule);
isInitializing = false;
}
@GuardedBy("Glide.class")
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
//实例化一个 GlideBuilder 在进行初始化
//GlideBuilder 默认的一些配置信息
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
再点击initializeGlide查看具体实现:
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
//1. 拿到应用级别的上下文,这里可以避免内存泄漏,我们实际开发也可以通过这种形式拿上下 文。
Context applicationContext = context.getApplicationContext();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
com.bumptech.glide.module.GlideModule current = iterator.next();
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
//2通过annotationGeneratedModule拿到RequestManagerFactory
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
//3将拿到的工厂添加到 GlideBuilder
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//4这里通过 Builder 建造者模式,构建出 Glide 实例对象
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
module.registerComponents(applicationContext, glide, glide.registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: "
+ module.getClass().getName(),
e);
}
}
if (annotationGeneratedModule != null) {
// 5开始注册组件回调
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
//6将构建出来的 glide 赋值给 Glide 的静态变量
Glide.glide = glide;
}
通过4 ,知道glide 是通过建造者生成的,具体建造者代码如下
@SuppressWarnings("PMD.ImmutableField")
public final class GlideBuilder {
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
//管理线程池
private Engine engine;
//对象池(享元模式),这样做避免重复创建对象,对内存开销有一定效果
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
private MemoryCache memoryCache;
//GlideExecutor 线程池
private GlideExecutor sourceExecutor;
//本地磁盘缓存
private GlideExecutor diskCacheExecutor;
private DiskCache.Factory diskCacheFactory;
//内存缓存
private MemorySizeCalculator memorySizeCalculator;
private ConnectivityMonitorFactory connectivityMonitorFactory;
private int logLevel = Log.INFO;
private RequestOptionsFactory defaultRequestOptionsFactory =
new RequestOptionsFactory() {
@NonNull
@Override
public RequestOptions build() {
return new RequestOptions();
}
};
@Nullable
private RequestManagerFactory requestManagerFactory;
private GlideExecutor animationExecutor;
private boolean isActiveResourceRetentionAllowed;
@Nullable
private List<RequestListener<Object>> defaultRequestListeners;
private boolean isLoggingRequestOriginsEnabled;
private boolean isImageDecoderEnabledForBitmaps;
/**
* 所有相关GlideBuilder都是一些配置信息,就删掉了
*
* @param bitmapPool
* @return
*/
@NonNull
public GlideBuilder setBitmapPool(@Nullable BitmapPool bitmapPool) {
this.bitmapPool = bitmapPool;
return this;
}
//开始构建glide
@NonNull
Glide build(@NonNull Context context) {
//实例化一个网络请求的线程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
//实例化一个本地磁盘缓存的线程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
//实例化一个加载图片动画的一个线程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//实例化一个对图片加载到内存的一个计算
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
//实例化一个默认网络连接监控的工厂
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
//实例化一个 Bitmap 对象池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
//如果池子里还有可用的,直接加入 最近最少使用的 LruBitmap 容器里
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
//如果池子已经满了,那么就装在 BitmapPoolAdapter
bitmapPool = new BitmapPoolAdapter();
}
}
//实例化一个数组对象池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
//资源内存缓存
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
//磁盘缓存的工厂
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
//构建执行缓存策略跟线程池的引擎
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//实例化一个 RequestManagerRetriever 请求管理类
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
//实例化 Glide 的地方 并返回
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
}
在上面代码中。builder主要构建了线程池、复用池、缓存策略、执行 Engine ,最后构建Glide实例,下面查看Glide构造函数:
@SuppressWarnings("PMD.UnusedFormalParameter")
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptionsFactory defaultRequestOptionsFactory,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
boolean isLoggingRequestOriginsEnabled,
boolean isImageDecoderEnabledForBitmaps) {
//将 Builder 构建的线程池,对象池,缓存池保存到 Glide 中
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;
//用于显示对应图片的工厂
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
//构建一个 Glide 专属的 上下文
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
}
public class GlideContext extends ContextWrapper {}
GlideContentx就是一个Context一个级别的上下文,到这里,我们就知道缓存策略、Glide、GlideContext 怎么构建出来的了。然后我们看下咱们获取请求管理类:RequestManager
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
在RequestManagerRetriever中这块返回了RequestManager,这里get也有很多重载函数
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
//如果在主线程中并且不为Application 级别的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) {
//一支查找BaseContext
return get(((ContextWrapper) context).getBaseContext());
}
}
//如果不在主线程或者为Application就直接执行
return getApplicationManager(context);
}
//通过Activity拿到RequestManager
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull Activity activity) {
//判断当前是否在子线程中请求任务
if (Util.isOnBackgroundThread()) {
//如果是子线程,通过 Application 级别的Context 加载
return get(activity.getApplicationContext());
} else {
//检查Activity是否销毁
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
//生成Fragment谭厚绑定一个请求管理器RequestManager
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
接下来点击fragmentGet方法:这个方法主要是给当前Activity添加一个fragment然后绑定glide,管理生命周期
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
@Deprecated
@NonNull
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//在当前activity添加一个fragment
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//拿到请求管理类
RequestManager requestManager = current.getRequestManager();
//如果不存在,则创建一个请求管理类,保持在当前的管理生命周期的Fragment中,相当于二者进行绑定,避免内存泄漏
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
//拿到单例glide
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
//返回当前请求管理者
return requestManager;
}
由上面得知,glide是通过fragment管理声明周期的,下面是具体查看fragment怎么添加到Activity中的:
这里上一个博客说过,先通过TAG去拿已经实例化过的fragment,如果这个fragment是空的,就去从缓冲中拿,如果缓存也没有,就去实例化一个fragment,然后去绑定声明周期,然后把这个fragment添加到map缓存中,然后给这个fragment设置TAG,然后通过handler发送消息,清理缓存
@SuppressWarnings("deprecation")
@NonNull
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
通过上述一系列流程,最后返回的需要的RequestManager对象:
在RequestManager构造方法中,有几行代码,执行添加了生命周期的监听和网络变化的监听
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
//添加的声明周期的监听,fragment传递过来的
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
//网络变化的监听
lifecycle.addListener(connectivityMonitor);
fragment给Glide的声明周期传递:
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
@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();
}
}
lifecycle :ActivityFragmentLifecycle实现了Glide中的Lifecycle 接口,注册是在RequestManagerFactory 工厂中实例化的 RequestManager 然后在构造函数中添加了生命周期回调监 听
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
/**
* Adds the given listener to the list of listeners to be notified on each lifecycle event.
*
* <p>The latest lifecycle event will be called on the given listener synchronously in this
* method. If the activity or fragment is stopped, {@link LifecycleListener#onStop()}} will be
* called, and same for onStart and onDestroy.
*
* <p>Note - {@link com.bumptech.glide.manager.LifecycleListener}s that are added more than once
* will have their lifecycle methods called more than once. It is the caller's responsibility to
* avoid adding listeners multiple times.
*/
@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();
}
}
}
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);
}
};
}
最后,在RequestManager中的三处回调就是fragment传递过来的:
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
/**
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
参考一位老师画的图,可以对一下流程:
二、load
load源码查看比较少,主要包含一下类:RequestManager,RequestBuilder
点击load先跳转RequestManager类:最后构建了一个RequestBuilder类
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
//这里调用Drawable 图片加载请求器为其加载
return asDrawable().load(string);
}
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
下面是RequestBuilder的创建代码:
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable, ModelTypes<RequestBuilder<TranscodeType>> {
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
// 描述加载的数据源-这里可以看做是我们刚刚传递进来的 http://xxxx.png
@Nullable private Object model;
// 描述这个请求是否已经添加了加载的数据源
private boolean isModelSet;
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true; return this;
}
}
三、info
info的流程大概有如下这些步骤:
RequestBuilder->into->buildRequest->buildRequestRecursive->obtainRequest-> SingleRequest
SingleRequest ->Request ->requestManager.track(target, request); 返回RequestManager-
RequestManager->requestTracker.runRequest(request)-》request.begin(); 到SingleRequest的onSizeReady
SingleRequest-》engine.load-》Engin->loadFromActiveResources/loadFromCache
Engine-》waitForExistingOrStartNewJob->jobs.get(key, onlyRetrieveFromCache)->engineJob.start(decodeJob);
EngineJob->willDecodeFromCache->executor.execute(decodeJob);
DecodeJob->run方法,执行线程->runWrapped() ->INITIALIZE->runGenerators ->getNextGenerator-
DecodeJob->SourceGenerator->currentGenerator.startNext()->DataCacheGenerator
DataCacheGenerator->startNext()->buildLoadData
HttpGlideUrlLoader->HttpUrlFetcher->loadDataWithRedirects-> urlConnection.connect()
HttpGlideUrlLoader-->getStreamForSuccessfulRequest->callback.onDataReady(result)
DataCacheGenerator->cb.onDataFetcherReady->DecodeJob->decodeFromRetrievedData();
->decodeFromData->decodeFromFetcher->runLoadPath->path.load->LoadPath:loadWithExceptionList
-> path.decode->DecodePath:decodeResource -> callback.onResourceDecoded -> onResourceDecoded
->DecodeJob:notifyEncodeAndRelease->notifyComplete(result, dataSource);
->callback.onResourceReady(resource, dataSource);->notifyCallbacksOfResult -
EngineJob>engineJobListener.onEngineJobComplete->Engine:activeResources.activate(key, resource);
SingleRequest->onResourceReady
ImageViewTarget:onResourceReady->setResource->DrawableImageViewTarget-> view.setImageDrawable(resource);
上面是into加载的流程,包含了网络请求、线程切换、数据渲染、不同尺寸图片等各种功能的实现,具体下面列出一些重要的方法调用:
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
// 根据ImageView 布局中的scaleType 来重构 requestOptions
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.
//如果在xml ImageView 节点中没有设置scaleType 那么默认在构造函数中进行了初始化mScaleType = ScaleType.FIT_CENTER;
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.
}
}
//调用into函数,创建一个ViewTarget
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
上面代码中,做了两个事情:
第一步:先拿到当前 ImageView getScaleType 类型的属性,然后重新 clone 一个进行配置;
第二步:调用 into 重载继续构建
在into方法函数中,glideContext.buildImageViewTarget 是调用工厂模式生成了一个对应的ImageViewTarget,在ImageViewTargetFactory工厂中判断传入的编码类型属于那个类型:
//如果目标的编码类型属于 Bitmap 那么就创建一个 Bitmap 类型的 ImageViewTarget
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
//如果目标的编码类型属于 Drawable 那么就创建一个 Drawable 类型的 ImageViewTarget
}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)");
}
继续点击into函数:
这里做了两个事情:
第一点:为 target buildRequest 构建一个 Glide request 请求;
第二点:将构建出来的 Request 交于 RequestManager 来执行;
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 request = buildRequest(target, targetListener, options, callbackExecutor);
//拿到上一个请求
Request previous = target.getRequest();
//判断请求是否冲突
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// 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()) {
// 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;
}
//清理掉旧的请求
requestManager.clear(target);
.//设置一个新的请求
target.setRequest(request);
//调用RequestManager的track执行目标的Glide request 请求
requestManager.track(target, request);
return target;
}
track函数执行:
//这里对当前class加了一个同步锁避免线程引起的安全性
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
//添加一个目标任务
targetTracker.track(target);
//执行Glide request
requestTracker.runRequest(request);
}
public void runRequest(@NonNull Request request) {
//添加一个请求,
requests.add(request);
if (!isPaused) {
//没有赞同,调用begin执行
request.begin();
} else {
//暂停了 清理请求
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
上面的逻辑是先为requests添加一个请求,看看是否是停止状态,如果不是就调用request.begin(); 执行。
这里的Request是一个接口,通过之前我们看到到 buildReques函数可知的requests实现类是Singl
eRequest我们就直接看它的begin函数.
@Override
public void begin() {
synchronized (requestLock) {
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;
//这里表示大小已经准备好了
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));
}
}
}
查看onSizeReady:
@Override
public void onSizeReady(int width, int height) {
loadStatus =
engine.load();
}
load方法:
public <R> LoadStatus load() {
//拿到缓存或者请求的key
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options); //根据key 拿到活动缓存中的资源
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
//如果ActiveResources 活动缓存中有就回调出去
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
return null;
}
//尝试从 LruResourceCache 中找寻这个资源
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
//如果内存缓存 Lru 中资源存在回调出去
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
return null;
}
//------------- 走到这里说明活动缓存 跟内存 缓存都没有找到 -----------
//根据 Key 看看缓存中是否正在执行
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
//如果正在执行,把数据回调出去
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// -------------- 走到这里说明是一个新的任务 ---------------
// -------------- 构建新的请求任务 ---------------
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//把当前需要执行的 key 添加进缓存
jobs.put(key, engineJob);
//执行任务的回调
engineJob.addCallback(cb, callbackExecutor); //开始执行。
engineJob.start(decodeJob);
return new LoadStatus(cb, engineJob);
}
通过engine.load这个函数,可以总结三点:
- 先构建请求或者缓存 KEY ;
- 根据 KEY 从内存缓存中查找对应的资源数据(ActiveResources(活动缓存,内部是一个 Map 用弱 引用持有),LruResourceCache),如果有就回调 对应监听的 onResourceReady 表示数据准备好 了。
- 从执行缓存中查找对应 key 的任务
- 如果找到了,就说明已经正在执行了,不用重复执行。
- 没有找到,通过 EngineJob.start 开启一个新的请求任务执行。
下面我们就来看下engineJob.start 具体执行逻辑::
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
//拿到 Glide 执行的线程池
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
//开始执行
executor.execute(decodeJob);
}
通过DecodeJob源码得主,他是实现了Runnable接口,这里GlideExecutor 线程池开始执行,然后回去找资源的执行器,执行一些数据缓存策略。
在HttpGlideUrlLoader有一个buildLoadData方法,这个方法是去加载数据的:
@Override
public LoadData<InputStream> buildLoadData(
@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
// spent parsing urls.
GlideUrl url = model;
if (modelCache != null) {
url = modelCache.get(model, 0, 0);
if (url == null) {
modelCache.put(model, 0, 0, model);
url = model;
}
}
int timeout = options.get(TIMEOUT);
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
这里返回的是一个HttpUrlFetcher,把这个给了LoadData加载器,然后这个加载器去开始加载数据:
在HttpUrlFetcher的loadData方法中,发现了返回了一个输入流:
@Override
public void loadData(
@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//http 请求,返回一个InputStream 输入流
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}
我们在点击loadDataWithRedirects这个实现方法,发现这里面使用了HttpURLConnection做网络请求,实现文件获取:
private InputStream loadDataWithRedirects(
URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
// Comparing the URLs using .equals performs additional network I/O and is generally broken.
// See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new HttpException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Stop the urlConnection instance of HttpUrlConnection from following redirects so that
// redirects will be handled by recursive calls to this method, loadDataWithRedirects.
urlConnection.setInstanceFollowRedirects(false);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect();
// Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new HttpException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
// Closing the stream specifically is required to avoid leaking ResponseBodys in addition
// to disconnecting the url connection below. See #2352.
cleanup();
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
到这里,我们就知道了,Glide底层是使用HttpURLConnection作为网络请求的,请求成功返回一个输入流,最后通过onDataReady回调到DecodeJob的onDataFetcherReady 函数中。
@Override
public void onDataFetcherReady(
Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey; //当前返回数据的 key
this.currentData = data;//返回的数据
this.currentFetcher = fetcher;//返回的数据执行器,这里可以理解为 HttpUrlFetcher
this.currentDataSource = dataSource;//数据来源 url
this.currentAttemptingKey = attemptedKey;
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
//解析返回回来的数据
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
//解析返回的数据
private void decodeFromRetrievedData() {
Resource<R> resource = null;
try {
// 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream , currentDataSource
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
//解析完成后,通知下去
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
然后就是做了一系列数据解析操作,显示deResource 将源数据解析成资源,然后在调用 DecodeCallback.onResourceDecoded 处理资源,在调用 ResourceTranscoder.transcode 将资源转为目标资源(目标资源类型: Drawable),然后在资源进行转换操作,这些操作都是在请求的时间进行的配置,然后构建磁盘缓存的key,最终将Bitmap 转换成 Drawable,
在DecodePath类中,这个方法:
public Resource<Transcode> decode(
DataRewinder<DataType> rewinder,
int width,
int height,
@NonNull Options options,
DecodeCallback<ResourceType> callback)
throws GlideException {
//调用decodeResourec将数据解析成中间资源Bitmap
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
//解析完数据回调出去
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
//转换资源为目标资源Bitmap to Drawable
return transcoder.transcode(transformed, options);
}
最后将我们解析到的 bitmap 存放到 LazyBitmapDrawableResource 内部, 然后外界通过 get 方法就可以获取到一个 BitmapDrawable 的对象了,解析完就到了展示数据了,然会在回到DecodeJob的decodeFromRetrievedData这个方法,点击
notifyEncodeAndRelease,这里会将资源做磁盘缓存:
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
//通知调用层数据已经装备好了
notifyComplete(result, dataSource);
stage = Stage.ENCODE;
try {
//这里就是将资源磁盘缓存
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
// Call onEncodeComplete outside the finally block so that it's not called if the encode process
// throws.
onEncodeComplete();
}
// 在DecodeJob 的构建中, 我们知道这个Callback 是EngineJob
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
}
通过上面的这些逻辑,我们知道DecodeJob.decodeFromRetrievedData做了几个处理,
1.解析返回回来的资源。
2.拿到解析的资源,如果配置了本地缓存,就缓存到磁盘。
3.通知上层资源准备就绪,可以使用了。
我们直接看EngineJob的onResourceReady回调函数:
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
void notifyCallbacksOfResult() {
。。。
//回调上层Engine 任务完成了
engineJobListener.onEngineJobComplete(this, localKey, localResource);
//遍历资源回调给 ImageViewTarget
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
通过上面 EngineJob 的 onResourceReady回调函数主要做了两个处理:
1.通知上层任务完成。
2.回调 ImageViewTarget 用于展示数据。
在 Engine实现了onEngineJobComplete方法,
@SuppressWarnings("unchecked")
@Override
public synchronized void onEngineJobComplete(
EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null && resource.isMemoryCacheable()) {
//收到下游返回回来的资源,添加到活动缓存中
activeResources.activate(key, resource);
}
jobs.removeIfCurrent(key, engineJob);
}
然后最终通知ImageViewTarget ,然后回走到SingleRequest类的onResourceReady方法:
@GuardedBy("requestLock")
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
...
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> 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);
//回调给目标 ImageViewTarget 资源准备好了
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
//加载成功
notifyLoadSuccess();
}
把准备好的资源回调给显示层,看下面代码
@SuppressWarnings("WeakerAccess")
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
// Order matters here. Set the resource first to make sure that the Drawable has a valid and
// non-null Callback before starting it.
//调用 setResource 函数,将资源显示出来
setResource(resource);
maybeUpdateAnimatable(resource);
}
}
在开始构建的时间,我们会调用asBitmap,它的实现类是DrawableImageViewTarget,我看下内部具体实现:
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
/** @deprecated Use {@link #waitForLayout()} instead. */
// Public API.
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
这里看到抽象类中调用了 setResource ,子类实现并调用view.setImageDrawable(resource); 图片现在算是真正的显示出来了。 我们就看到了图片的显示。
在放一张一位老师准备的流程图,供大家参考:
四、生命周期的意义
就是Glide框架内部会搞一个空白的Fragment关联到用户的 Activity或者Fragment,当用户的 Activity或者Fragment发生Stop,Start 的时候,空白的Fragment就监听到了,从而根据用户Activity或者Fragment的变化,从而做出自己框架的处理