前言
Glide是一款功能强大的图片加载框架,它功能强大,用法简单且易于扩展,同时也是Google推荐的Android平台图片加载库,堪称优秀。
本章拆解思路
这算是开篇第一章吧,我准备从入口类和简单的调用流程说起,包括但不限于:
- Glide的构造
- RequestManager和生命周期监听
- Request和配置的收集
- Target以及触发异步加载
Glide对象初始化
从with()说起
为何要从with()方法,明明初始化代码在get()方法中:
Glide.java
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
//get方法获取单例对象
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
//with方法调用,获取RequestManagerRetriever对象
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();
}
//检查和初始化Glide
private static void checkAndInitializeGlide(@NonNull Context context) {
// 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);
isInitializing = false;
}
复制代码
with()和get()区别是啥?
两者最终都会调用到get()方法,区别是with()方法会返回一个RequestManager对象,get方法会返回Glide对象,Glide是一个单例模式,在get()中调用checkAndInitializeGlide()方法,checkAndInitializeGlide()方法对初始化的判断
真正执行初始化的调用initializeGlide();
解析注解配置项
Glide.java
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());//GlideBuilder在此处创建
}
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List manifestModules = Collections.emptyList();
//代码1 判断是否使用清单文件配置模块
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
//代码2 删掉排除的类
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
Iterator 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());
}
}
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
//代码3 循环调用清单配置模块applyOptions方法
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
//代码4 调用注解配置模块applyOptions方法
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//代码7 关键代码创建Glide对象
Glide glide = builder.build(applicationContext);
//代码5 循环调用清单配置模块registerComponents方法
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
//代码6 调用注解配置模块registerComponents方法
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
复制代码
initializeGlide还有一个重载的方法,不过被标识过期了,但是核心的逻辑都在这里啊。
我们发现GlideBuilder在此创建,进入这个过时的方法,该方法先是操作annotationGeneratedModule和manifestModules,注释在代码1~6中有讲解,这两种Module主要是针对Glide的配置,在Glide v3版本中,使用GlideModule和清单文件中配置,而在V4版本中,废弃了GlideModule接口,不推荐使用清单文件配置,建议用AppGlideModule,LibraryGlideModule接口和编译时注解@GlideModule,具体如何使用清单配置不赘述,借用官方的一个注解配置示例.
例如,v3 版本中 Volley 集成库的 GlideModule :
public class VolleyGlideModule implements GlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// Do nothing.
}
@Override
public void registerComponents(Context context, Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
}
}
在 v4 版本中可以转换成为一个 LibraryGlideModule :
@GlideModule
public class VolleyLibraryGlideModule extends LibraryGlideModule {
@Override
public void registerComponents(Context context, Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
}
}
复制代码
解析注解/清单文件和构造Glide的要有先后顺序:
GlideModule
的主要功能是让用户配置Register和GlideBuilder,在构建Glide之前,将配置选择添加进去;
接着上面initializeGlide讲解,代码7处主要是调用GlideBuilder.build()方法得到Glide对象,代码7必须得在配置模块执行applyOptions之前和执行registerComponents之后调用,为什么?
因为applyOptions(Context context, GlideBuilder builder)方法目的是配置Glide,肯定要执行在builder.build()之前;
registerComponents(Context context, Registry registry)方法配置register,register必须等到Glide创建之后,才能初始化调用。
剩下就是GlideBuilder执行build()方法;
GlideBuilder创建默认参数
GlideBuilder.java
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();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
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(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
复制代码
GlideBuilder主要是为Glide的创建,提供默认配置项和用户配置项,在上面我们说GlideModule和LibraryGlideModule中applyOptions(Context context, GlideBuilder builder)方法,得到GlideBuilder对象就可以设置相关的配置;详见GlideBuilder.setXXX()方法;
构造方法和创建Registry
接下来就是真正的调用Glide构造方法了
Glide.java
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 RequestOptions defaultRequestOptions,
@NonNull Map, TransitionOptions, ?>> defaultTransitionOptions) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
final Resources resources = context.getResources();
registry = new Registry();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
registry.register(new DefaultImageHeaderParser());
Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
resources.getDisplayMetrics(), bitmapPool, arrayPool);
ByteBufferGifDecoder byteBufferGifDecoder =
new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);
ResourceDecoder parcelFileDescriptorVideoDecoder =
VideoDecoder.parcel(bitmapPool);
ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
ResourceDrawableDecoder resourceDrawableDecoder =
new ResourceDrawableDecoder(context);
ResourceLoader.StreamFactory resourceLoaderStreamFactory =
new ResourceLoader.StreamFactory(resources);
ResourceLoader.UriFactory resourceLoaderUriFactory =
new ResourceLoader.UriFactory(resources);
ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
new ResourceLoader.FileDescriptorFactory(resources);
ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory =
new ResourceLoader.AssetFileDescriptorFactory(resources);
BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);
BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();
ContentResolver contentResolver = context.getContentResolver();
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
/* Bitmaps */
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
//此处省略好多append方法
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext = new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
engine,
logLevel);
}
复制代码
Glide构造方法除了接受GlideBuilder提供的参数之外,还创建了Registry对象和一堆组件;Registry是整个Glide运转的核心功能之一,也是我们后面文章即将讲到的重点;整理一下Glide构造方法遇到的比较重要的参数: engine
、memoryCache
、bitmapPool
、arrayPool
、requestManagerRetriever
、connectivityMonitorFactory
、defaultRequestOptions
、defaultTransitionOptions
、registry
、glideContext
等。 构造环节就讲到这里,下面从with()方法开始,继续往下分析;
with()
上文已经说到with一共有五个重载的方法,最终都调用Glide.getRetriever()方法得到RequestManagerRetriever
对象,然后调用RequestManagerRetriever.get()
方法,得到RequestManager
对象
下面来看一下RequestManagerRetriever
的get方法:
RequestManagerRetriever.java
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) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
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));
}
}
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(fragment.getActivity(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
@SuppressWarnings("deprecation")
@NonNull
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));
}
}
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull View view) {
if (Util.isOnBackgroundThread()) {
return get(view.getContext().getApplicationContext());
}
Preconditions.checkNotNull(view);
Preconditions.checkNotNull(view.getContext(),
"Unable to obtain a request manager for a view without a Context");
Activity activity = findActivity(view.getContext());
// The view might be somewhere else, like a service.
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
// Support Fragments.
// Although the user might have non-support Fragments attached to FragmentActivity, searching
// for non-support Fragments is so expensive pre O and that should be rare enough that we
// prefer to just fall back to the Activity directly.
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
return fragment != null ? get(fragment) : get(activity);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
复制代码
RequestManagerRetriever.get()
方法重载,我们分析一下调用过程:
- 当前调用运行在子线程时,直接把context转成Application调用
- 当运行在主线程时,
- 如果参数为support下的Fragment或FragmentActivity,调用supportFragmentGet(),
- 如果参数为android包下的Activity或Fragment,调用fragmentGet()方法,
- 如果参数为Application,调用getApplicationManager()方法,
- 如果参数为View,获取View对应的Context,判断Context类型,调用上面的几个重载方法;
接下来的调用就在getApplicationManager()、supportFragmentGet(),由于fragmentGet()方法已经过时且逻辑和supportFragmentGet()大同小异,所以就不分析它了:
RequestManagerRetriever.java
private RequestManager getApplicationManager(@NonNull Context context) {
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
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) {
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
private final RequestManagerFactory factory;
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
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);
}
};
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingSupportRequestManagerFragments.put(fm, current);//通过事务添加frg
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
复制代码
上面两个方法最后真正创建RequestManager的是factory.build(),factory是RequestManagerFactory中默认的DEFAULT_FACTORY静态变量;supportFragmentGet()方法中调用getSupportRequestManagerFragment方法创建了SupportRequestManagerFragment对象并通过Transaction.add(fragment,tag)方法提交;
所有问题转换为RequestManager的作用,以及SupportRequestManagerFragment和Lifecycle的意义;
先从SupportRequestManagerFragment分析;
SupportRequestManagerFragment.java
private final ActivityFragmentLifecycle lifecycle;
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
ActivityFragmentLifecycle getGlideLifecycle() {
return 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();
}
复制代码
ActivityFragmentLifecycle.java
class ActivityFragmentLifecycle implements Lifecycle {
private final Set lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap());
private boolean isStarted;
private boolean isDestroyed;
@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();
}
}
}
复制代码
LifecycleListener.java
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
复制代码
Lifecycle.java
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
复制代码
SupportRequestManagerFragment的构造方法创建了ActivityFragmentLifecycle()对象,然后再fragment对应的onStart()、onStop()、onDestory()方法中调用lifecycle的对应方法;
看到这里有点明白了,Lifecycle是根据Fragment的生命周期而产生;ActivityFragmentLifecycle类持有LifecycleListener泛型的Set集合,在对应的onStart()、onStop()、onDestory()调用Set集合中的LifecycleListener对应的方法;
至此我们可以得到一张生命周期的调用链:SupportRequestManagerFragment->Lifecycle->LifecycleListener;
我们回到对RequestManager的理解,上文分析了RequestManagerRetriever中创建RequestManager,传递了Lifecycle参数,下面分析RequestManager的构造和以及它和Lifecycle的关系;
RequestManager.java
//实现了LifecycleListener接口
public class RequestManager implements LifecycleListener{
private final RequestTracker requestTracker;
private final TargetTracker targetTracker = new TargetTracker();
//主线程中执行
private final Runnable addSelfToLifecycle = new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
};
//构造方法
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;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
if (Util.isOnBackgroundThread()) {
//在主线程中执行
mainHandler.post(addSelfToLifecycle);
} else {
//把自身加入生命周期的监听中
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
@Override
public void onStart() {
resumeRequests();
targetTracker.onStart();//targetTracker监听
}
@Override
public void onStop() {
pauseRequests();
targetTracker.onStop();//targetTracker监听
}
public void resumeRequests() {
Util.assertMainThread();
requestTracker.resumeRequests();//requestTracker监听
}
public void pauseRequests() {
Util.assertMainThread();
requestTracker.pauseRequests();//requestTracker监听
}
@Override
public void onDestroy() {
targetTracker.onDestroy();//targetTracker监听
for (Target> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();//targetTracker监听
requestTracker.clearRequests();//requestTracker监听
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
}
复制代码
RequestManager自身实现了LifecycleListener接口,在构造方法中获得Lifecycle对象然后把自身addListener,在对应的onStart()、onStop()、onDestory()方法中调用调用RequestTracker和TargetTracker的对应生命周期方法,完成了生命周期的传递;
最终要用到这三个生命周期的对想是RequestTracker和TargetTracker这两个类,后面会用上他们。
load()
紧接上文,Glide.with()之后获得RequestManager对象,load()方法自然是RequestManager对象的,RequestManager实现了ModelTypes接口,ModelTypes接口正是这一些列load方法的定义者。
ModelTypes.java
interface ModelTypes {
@NonNull
@CheckResult
T load(@Nullable Bitmap bitmap);
@NonNull
@CheckResult
T load(@Nullable Drawable drawable);
@NonNull
@CheckResult
T load(@Nullable String string);
@NonNull
@CheckResult
T load(@Nullable Uri uri);
@NonNull
@CheckResult
T load(@Nullable File file);
@NonNull
@CheckResult
T load(@RawRes @DrawableRes @Nullable Integer resourceId);
@Deprecated
@CheckResult
T load(@Nullable URL url);
@NonNull
@CheckResult
T load(@Nullable byte[] model);
@NonNull
@CheckResult
@SuppressWarnings("unchecked")
T load(@Nullable Object model);
}
复制代码
ModelTypes定义了8个重载方法load(),支持参数类型:Bitmap
、Drawable
、String
、Uri
、File
、Integer
、URL
、byte
、Object
;
它的实现类RequestManager是怎么做具体的实现 RequestManager.java
public class RequestManager implements LifecycleListener,
ModelTypes> {
public RequestBuilder load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
public RequestBuilder load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder load(@Nullable Uri uri) {
return asDrawable().load(uri);
}
public RequestBuilder asDrawable() {
return as(Drawable.class);
}
public RequestBuilderifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}
public RequestBuilder as(
@NonNull Class resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
}
复制代码
RequestManager实现了ModelTypes接口并且返回类型为RequestBuilder,重写了load(xxx)方法,所有的操作都是调用asDrawable().load(xxx)方法,真正执行load的还是asDrawable()返回的对象,
除了asDrawable(),还有asGif()、asFile()、as(Class)等方法,其中asGif(),asFile()本质上还是调用as(Class)来实现,这个as(Class)方法创建了RequestBuilder对象,所以这个as()方法调用就是创建RequestBuilder的,真正load的还是RequestBuilder,
再说说类型,as()方法支持泛型,load()方法支持8种类型(其中包括Object),这意味着,我们可以load()任意自定义类型,返回任意自定义类型的RequestBuilder,这个疑问先放一放,从load()方法追踪RequestBuilder这个类;
RequestBuilder.java
public RequestBuilder load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder load(@Nullable Drawable drawable) {
return loadGeneric(drawable)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}
public RequestBuilder load(@Nullable String string) {
return loadGeneric(string);
}
public RequestBuilder load(@Nullable Uri uri) {
return loadGeneric(uri);
}
public RequestBuilder load(@Nullable File file) {
return loadGeneric(file);
}
private RequestBuilder loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
public RequestBuilder load(@Nullable Object model) {
return loadGeneric(model);
}
复制代码
从load方法来看,最终都调用loadGeneric(Object model),loadGeneric()也只是对model和isModelSet进行赋值,仅此而已,
但是load(Bitmap)和load(Drawable)默认设置了apply(diskCacheStrategyOf(DiskCacheStrategy.NONE),说明直接加载Bitmap和Drawable是不需要DiskCache的,load方法走到这里就结束了。
load流程总结: 在RequestManager中确定model和SourceType,然后创建RequestBuilder对象,再把model信息传递给RequestBuilder,完成了load流程。
apply()
在Glide实际运用中,简单的调用Glide.with.load.into是远远不够的,我们可能需要更多的配置,比如有占位图,圆角剪裁,缩略图等场景,这就要调用RequestBuilder.apply()方法,该方法接受一下RequestOptions参数,我们从apply()方法和RequestOptions类来分析:
RequestBuilder.java
public RequestBuilder apply(@NonNull RequestOptions requestOptions) {
Preconditions.checkNotNull(requestOptions);
this.requestOptions = getMutableOptions().apply(requestOptions);
return this;
}
protected RequestOptions getMutableOptions() {
return defaultRequestOptions == this.requestOptions
? this.requestOptions.clone() : this.requestOptions;
}
复制代码
RequestBuilder持有requestOptions,apply()方法主要流程是拿当前的requestOptions,调用RequestOptions.apply组合配置;
RequestOptions.java
public RequestOptions apply(@NonNull RequestOptions other) {
if (isAutoCloneEnabled) {
return clone().apply(other);
}
if (isSet(other.fields, SIZE_MULTIPLIER)) {
sizeMultiplier = other.sizeMultiplier;
}
if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) {
useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool;
}
if (isSet(other.fields, USE_ANIMATION_POOL)) {
useAnimationPool = other.useAnimationPool;
}
if (isSet(other.fields, DISK_CACHE_STRATEGY)) {
diskCacheStrategy = other.diskCacheStrategy;
}
if (isSet(other.fields, PRIORITY)) {
priority = other.priority;
}
if (isSet(other.fields, ERROR_PLACEHOLDER)) {
errorPlaceholder = other.errorPlaceholder;
errorId = 0;
fields &= ~ERROR_ID;
}
if (isSet(other.fields, ERROR_ID)) {
errorId = other.errorId;
errorPlaceholder = null;
fields &= ~ERROR_PLACEHOLDER;
}
if (isSet(other.fields, PLACEHOLDER)) {
placeholderDrawable = other.placeholderDrawable;
placeholderId = 0;
fields &= ~PLACEHOLDER_ID;
}
if (isSet(other.fields, PLACEHOLDER_ID)) {
placeholderId = other.placeholderId;
placeholderDrawable = null;
fields &= ~PLACEHOLDER;
}
if (isSet(other.fields, IS_CACHEABLE)) {
isCacheable = other.isCacheable;
}
if (isSet(other.fields, OVERRIDE)) {
overrideWidth = other.overrideWidth;
overrideHeight = other.overrideHeight;
}
if (isSet(other.fields, SIGNATURE)) {
signature = other.signature;
}
if (isSet(other.fields, RESOURCE_CLASS)) {
resourceClass = other.resourceClass;
}
if (isSet(other.fields, FALLBACK)) {
fallbackDrawable = other.fallbackDrawable;
fallbackId = 0;
fields &= ~FALLBACK_ID;
}
if (isSet(other.fields, FALLBACK_ID)) {
fallbackId = other.fallbackId;
fallbackDrawable = null;
fields &= ~FALLBACK;
}
if (isSet(other.fields, THEME)) {
theme = other.theme;
}
if (isSet(other.fields, TRANSFORMATION_ALLOWED)) {
isTransformationAllowed = other.isTransformationAllowed;
}
if (isSet(other.fields, TRANSFORMATION_REQUIRED)) {
isTransformationRequired = other.isTransformationRequired;
}
if (isSet(other.fields, TRANSFORMATION)) {
transformations.putAll(other.transformations);
isScaleOnlyOrNoTransform = other.isScaleOnlyOrNoTransform;
}
if (isSet(other.fields, ONLY_RETRIEVE_FROM_CACHE)) {
onlyRetrieveFromCache = other.onlyRetrieveFromCache;
}
if (!isTransformationAllowed) {
transformations.clear();
fields &= ~TRANSFORMATION;
isTransformationRequired = false;
fields &= ~TRANSFORMATION_REQUIRED;
isScaleOnlyOrNoTransform = true;
}
fields |= other.fields;
options.putAll(other.options);
return selfOrThrowIfLocked();
}
复制代码
注意到RequestOptions有一个int类型成员变量fields,apply方法一直在调用isSet()方法做判断,isSet()逻辑是如果传入的这个RequestOptions对象other设置了xxx属性,就替换掉现有的属性,如果特殊情况再清楚掉其他标志位,下面着重分析一下fields标志位;
RequestOptions标志位
上文提到fields,分析它是用来标志各个属性是否被赋值,我们就拿常用了placeholder()方法来分析,placeholder()有两个重载方法
RequestOptions.java
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;
public RequestOptions placeholder(@Nullable Drawable drawable) {
if (isAutoCloneEnabled) {
return clone().placeholder(drawable);
}
this.placeholderDrawable = drawable;
fields |= PLACEHOLDER;//给代表drawable的placeholder标志位至1
placeholderId = 0;
fields &= ~PLACEHOLDER_ID;//给代表id的placeholder标志位至0
return selfOrThrowIfLocked();
}
public RequestOptions placeholder(@DrawableRes int resourceId) {
if (isAutoCloneEnabled) {
return clone().placeholder(resourceId);
}
this.placeholderId = resourceId;
fields |= PLACEHOLDER_ID;//给代表id的placeholder标志位至1
placeholderDrawable = null;
fields &= ~PLACEHOLDER;//给代表drawable的placeholder标志位至0
return selfOrThrowIfLocked();
}
private static boolean isSet(int fields, int flag) {
return (fields & flag) != 0;
}
复制代码
placeholder(drawable)和placeholder(resourceId)这两个方法不能同时对placeholder这一实物产生效果,所以会有fields |= PLACEHOLDER和fields &= ~PLACEHOLDER_ID这样的代码,
系统定义了21个标志位,通过每个标志位代表RequestOptions对应属性的赋值与否,巧妙使用位运算,用一个int类型表示了21个bool逻辑(其实一个int最多能标识32个逻辑),当然这种位运算也是Android源码中非常常见的。
RequestOptions的其他方法暂时不过多介绍,我们还是回到主干调用流程,上面讲到了load()和apply()方法,这两个方法主要是收集用户的配置信息,真正触发逻辑的入口是into()方法;
into()流程
RequestBuilder.java
@NonNull
public > Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null);
}
@NonNull
@Synthetic > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener) {
return into(target, targetListener, getMutableOptions());
}
private > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
//创建Request
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// 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设置request
target.setRequest(request);
//跟踪target和request
requestManager.track(target, request);
return target;
}
复制代码
RequestBuilder的into()方法代码量并不大,主要做了这些事:
- 创建Request对象,
- 将request设置给target
- requestManager跟踪request和target;
之前一直在说RequestBuilder,顾名思义RequestBuilder是Request的建造者,Request才是真正的大佬;
Request.java
public interface Request {
void begin();
void clear();
boolean isRunning();
boolean isComplete();
boolean isResourceSet();
boolean isCleared();
boolean isFailed();
void recycle();
boolean isEquivalentTo(Request other);
}
复制代码
Request不是一个具体的类,它定义了Request该有的方法,其中begin()方法开始一个异步加载,
Request实现类有三个: ErrorRequestCoordinator
,ThumbnailRequestCoordinator
、SingleRequest
,先不细说Request,回到主流程Request的创建是由Builder类完成,RequestBuilder如何构建Request对象的:
在分析Request构建之前,我觉得有必要写一下Glide缩略图
和失败新请求
的用法:
缩略图 (Thumbnail) 请求
Glide 的 thumbnail() API 允许你指定一个 RequestBuilder 以与你的主请求并行启动。thumbnail() 会在主请求加载过程中展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。
Glide.with(fragment)
.load(url)
.thumbnail(Glide.with(fragment)
.load(thumbnailUrl))
.into(imageView);
复制代码
thumbnail() 方法有一个简化版本,它只需要一个 sizeMultiplier 参数。如果你只是想为你的加载相同的图片,但尺寸为 View 或 Target 的某个百分比的话特别有用:
Glide.with(fragment)
.load(localUri)
.thumbnail(/*sizeMultiplier=*/ 0.25f)
.into(imageView);
复制代码
在失败时开始新的请求
可以使用 error API 来指定一个 RequestBuilder,以在主请求失败时开始一次新的加载。例如,在请求 primaryUrl 失败后加载 fallbackUrl
Glide.with(fragment)
.load(primaryUrl)
.error(Glide.with(fragment)
.load(fallbackUrl))
.into(imageView);
复制代码
如果主请求成功完成,这个error RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail() 和一个 error() RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。
以上关于缩略图和fallback大部分内容都是来自Glide官方示例。
RequestBuilder.java
private Float thumbSizeMultiplier;
RequestBuilder errorBuilder;
private RequestBuilder thumbnailBuilder;
public RequestBuilder error(@Nullable RequestBuilder errorBuilder) {
this.errorBuilder = errorBuilder;
return this;
}
public RequestBuilder thumbnail(
@Nullable RequestBuilder thumbnailRequest) {
this.thumbnailBuilder = thumbnailRequest;
return this;
}
public RequestBuilder thumbnail(float sizeMultiplier) {
if (sizeMultiplier < 0f || sizeMultiplier > 1f) {
throw new IllegalArgumentException("sizeMultiplier must be between 0 and 1");
}
this.thumbSizeMultiplier = sizeMultiplier;
return this;
}
复制代码
其中thumbnail和error支持传入一个新的RequestBuilder,而且thumbnail是支持float(0-1.0)参数进行比例等比缩小的f方式。
构建Request流程
接下来看一下Request实例如何被创建处理;
RequestBuilder.java
private Request buildRequest(
Target target,
@Nullable RequestListener targetListener,
RequestOptions requestOptions) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions);
}
private Request buildRequestRecursive(
Target target,
@Nullable RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
//判断是否需要创建带有errorRequest的嵌套Request类
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {//意味着这(标记1)调用的
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
//得到可能带有缩略图嵌套的请求类
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions);
//不带error直接返回mainRequest
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.requestOptions.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
//调用当前方法,构建带error请求 (标记1)
Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
//创建带缩略图的请求类
private Request buildThumbnailRequestRecursive(
Target target,
RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
//thumbnailBuilder不为空
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a "
+ "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
}
//获取缩略图配置参数
TransitionOptions, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority = thumbnailBuilder.requestOptions.isPrioritySet()
? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.requestOptions.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
//源Request
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
isThumbnailBuilt = true;
// 缩略图的Request
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder.requestOptions);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {//缩略图缩放比例不为空
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
//源Request
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
RequestOptions thumbnailOptions = requestOptions.clone()
.sizeMultiplier(thumbSizeMultiplier);
// 缩略图的Request
Request thumbnailRequest =
obtainRequest(
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight);
//结合在一起
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
//无缩略图,直接返回源Request
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
}
}
private Request obtainRequest(
Target target,
RequestListener targetListener,
RequestOptions requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight) {
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory());
}
复制代码
构建嵌套Request核心流程
代码有点长,不过流程还不算复杂,主要涉及到errorRequest,thumbnailRequest,fullRequest,逻辑判断流程如下;
先判断errorRequest逻辑
- 判断用户是否设置过errorRequest,没有的话直接创建带有缩略图的mainRequest(不一定真的有缩略图);
- 如果设置过errorRequest,拿errorRequest对象调用buildRequestRecursive,创建errorRequest请求
- 用ErrorRequestCoordinator包装errorRequest和mainRequest。
再判断thumbnailRequest逻辑
- 如果用户设置了thumbnailBuilder,取配置参数,创建fullRequest和thumbRequest,然后用ThumbnailRequestCoordinator包装返回;
- 如果用户设置了thumbSizeMultiplier,创建fullRequest和thumbRequest,然后用ThumbnailRequestCoordinator包装返回;
- 用户没有缩略图,只创fullRequest;
ps:
其中fullRequest和mainRequest表示原始的请求,thumbRequest表示缩略图请求,errorRequest表示错误重使请求;
如果用户同时设置了error和thumbnail,最终生成的模型应该是ErrorRequestCoordinator(ThumbnailRequestCoordinator(fullRequest,thumbRequest),errorRequest);
值得注意到是,以Coordinator结尾的连个Request类并不执行真的的Request逻辑,真正执行逻辑的类是SingleRequest
;
SingleRequest分析
接下来就是SingleRequest咯,相关代码:
SingleRequest.java
public final class SingleRequest implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
public void begin() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {//如果尺寸已经确定,调用onSizeReady
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);//从Target身上获取Size
}
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));
}
}
@Override
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
if (IS_VERBOSE_LOGGABLE) {
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.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this);
if (status != Status.RUNNING) {
loadStatus = null;
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
}
复制代码
我们这里只分析SingleRequest最关键的两个方法onSizeReady()和begin();
这里有个疑问:begin的调用时候由谁触发?
记得在into()方法中,调用了requestManager.track(target, request)方法,该方法会调用requestTracker.runRequest(request), 看一下requestTracker;
RequestTracker.java
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();//begin
} else {
request.clear();
pendingRequests.add(request);
}
}
复制代码
SingleRequest的begin应该就是这货调用起来的;
SingleRequest尺寸问题
再继续分析SingleRequest尺寸问题:
Glide设计之初Size尺寸这一概念就很重视,竟然把真正执行异步加载的入口放在尺寸的回调函数onSizeReady()当中,
有没有可能在begin()的时候已经得到尺寸,其实有可能的,例如用户通过override
定义了尺寸;
除此之外,尺寸信息从何而来,我们能看到的是SingleRequest继承SizeReadyCallback接口和重写onSizeReady,在begin()方法中发现调用target.getSize(this);这一点就是获取尺寸的伏笔,Traget是可以提供尺寸信息的;
Target是接口
紧接上面的into()方法,该方法主要接受参数类型Target或者ImageView
如果参数类型是ImageView,Glide最终也是创建Target,这一点在下面代码可以说明;
public ViewTarget into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
//如果requestOptions设置了Transformation且允许,会自动添加imagView.ScaleType对应的Transformation
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);
}
复制代码
上面也说了,into(ImageView)本质上还是调用into(Target),除此之外,requestOptions可能会自动为Bitmap设置剪裁模式;
下面正式来到Target分析。Target本质上是一个接口,在早期版本中大家比较常用的是SimpleTarget,不过这一版SimpleTarget不建议使用了
看一下Target这个接口:
Target.java
public interface Target extends LifecycleListener {
int SIZE_ORIGINAL = Integer.MIN_VALUE;
void onLoadStarted(@Nullable Drawable placeholder);
void onLoadFailed(@Nullable Drawable errorDrawable);
void onResourceReady(@NonNull R resource, @Nullable Transition super R> transition);
void onLoadCleared(@Nullable Drawable placeholder);
void getSize(@NonNull SizeReadyCallback cb);
void removeCallback(@NonNull SizeReadyCallback cb);
void setRequest(@Nullable Request request);
@Nullable
Request getRequest();
}
复制代码
Target继承自LifecycleListener,还记得上文讲的LifecycleListener和RequestManager以及Fragment都是有千丝万缕的关系,onResourceReady(),onLoadFailed()相信大家也不陌生,还有setRequest()在into流程中也见过,
除此之外,还有一个关键的方法:void getSize(@NonNull SizeReadyCallback cb);
上文说到:SingleRequest真正执行engine.loade是触发onSizeReady方法,假设用户没有设置明确的SIZE,Target是如何计算尺寸的;
Target计算尺寸
SimpleTarget获取尺寸
我们首先来看SimpleTarget,这个类在前些版本还很受欢迎,这个版本已经淘汰了,我们分析SimageTarget对Size是如何处理的:
SimpleTarget
public abstract class SimpleTarget extends BaseTarget {
private final int width;
private final int height;
public SimpleTarget() {
this(SIZE_ORIGINAL, SIZE_ORIGINAL);
}
@SuppressWarnings("WeakerAccess")
public SimpleTarget(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public final void getSize(@NonNull SizeReadyCallback cb) {
if (!Util.isValidDimensions(width, height)) {
throw new IllegalArgumentException(
"Width and height must both be > 0 or Target#SIZE_ORIGINAL, but given" + " width: "
+ width + " and height: " + height + ", either provide dimensions in the constructor"
+ " or call override()");
}
cb.onSizeReady(width, height);
}
@Override
public void removeCallback(@NonNull SizeReadyCallback cb) {
// Do nothing, we never retain a reference to the callback.
}
}
复制代码
SimpleTarget构造方法可以传递size参数,一般我们使用SimpleTarget无参构造,无参构造默认用SIZE_ORIGINAL设置宽高加载原图尺寸,当然Gilde不建议我们这样做,如果原图太大的话,会造成内存加载过大甚至OOM,当然如果我们有特殊需求,也是可以的,然而现在4.8.0版本该方法已经被标识为过时,官方建议用CustomViewTarget
。
CustomViewTarget获取尺寸
看看CustomViewTarget有什么区别:
CustomViewTarget.java
public abstract class CustomViewTarget implements Target {
private static final String TAG = "CustomViewTarget";
@IdRes private static final int VIEW_TAG_ID =
R.id.glide_custom_view_target_tag;
private final SizeDeterminer sizeDeterminer;//尺寸获取
protected final T view;
@Nullable private OnAttachStateChangeListener attachStateListener;
private boolean isClearedByUs;
private boolean isAttachStateListenerAdded;
@IdRes private int overrideTag;
public CustomViewTarget(@NonNull T view) {
this.view = Preconditions.checkNotNull(view);
sizeDeterminer = new SizeDeterminer(view);
}
}
//获取尺寸
public final void getSize(@NonNull SizeReadyCallback cb) {
sizeDeterminer.getSize(cb);
}
static final class SizeDeterminer {
static Integer maxDisplayLength;
private final View view;
private final List cbs = new ArrayList<>();
//构造方法
SizeDeterminer(@NonNull View view) {
this.view = view;
}
//通知SizeReadyCallback
private void notifyCbs(int width, int height) {
for (SizeReadyCallback cb : new ArrayList<>(cbs)) {
cb.onSizeReady(width, height);
}
}
void checkCurrentDimens() {
if (cbs.isEmpty()) {
return;
}
int currentWidth = getTargetWidth();
int currentHeight = getTargetHeight();
if (!isViewStateAndSizeValid(currentWidth, currentHeight)) {
return;
}
notifyCbs(currentWidth, currentHeight);
clearCallbacksAndListener();
}
//从CustomViewTarget.getSize调用
void getSize(@NonNull SizeReadyCallback cb) {
int currentWidth = getTargetWidth();
int currentHeight = getTargetHeight();
if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
cb.onSizeReady(currentWidth, currentHeight);
return;
}
if (!cbs.contains(cb)) {
cbs.add(cb);
}
if (layoutListener == null) {
ViewTreeObserver observer = view.getViewTreeObserver();
layoutListener = new SizeDeterminerLayoutListener(this);
observer.addOnPreDrawListener(layoutListener);
}
}
//获取宽
private int getTargetHeight() {
int verticalPadding = view.getPaddingTop() + view.getPaddingBottom();
LayoutParams layoutParams = view.getLayoutParams();
int layoutParamSize = layoutParams != null ? layoutParams.height : PENDING_SIZE;
return getTargetDimen(view.getHeight(), layoutParamSize, verticalPadding);
}
//获取高
private int getTargetWidth() {
int horizontalPadding = view.getPaddingLeft() + view.getPaddingRight();
LayoutParams layoutParams = view.getLayoutParams();
int layoutParamSize = layoutParams != null ? layoutParams.width : PENDING_SIZE;
return getTargetDimen(view.getWidth(), layoutParamSize, horizontalPadding);
}
//从View身上获取尺寸的监听
private static final class SizeDeterminerLayoutListener
implements ViewTreeObserver.OnPreDrawListener {
private final WeakReference sizeDeterminerRef;
SizeDeterminerLayoutListener(@NonNull SizeDeterminer sizeDeterminer) {
sizeDeterminerRef = new WeakReference<>(sizeDeterminer);
}
@Override
public boolean onPreDraw() {
SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();
if (sizeDeterminer != null) {
sizeDeterminer.checkCurrentDimens();
}
return true;
}
}
}
}
复制代码
CustomViewTarget
把所有尺寸的获取都放到SizeDeterminer
这个类当中,SizeDeterminer
是内部类, SizeDeterminer
构造方法传入tragetView,然后通过ViewTreeObserver.OnPreDrawListener
的回调来获取targetView的确切宽度,最后再回调给SizeReadyCallback
对象。
结合上面说到的SingleRequest实现了SizeReadyCallback接口和target的关联,最终尺寸由SizeDeterminer
进行回调。
所以:Request的触发加载是由尺寸回调驱动,而Target是尺寸的提供者;
最后,into(ImageView)默认创建的Target如何把结果设置给ImageView的,其实Glide源码中定义了很多Target,比如ImageViewTarget,默认是由ImageViewTargetFactory创建;
ImageViewTargetFactory是Glide初始化流程中创建了,代码很简单: ImageViewTargetFactory.java
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public ViewTarget buildTarget(@NonNull ImageView view,
@NonNull Class clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
}
复制代码
最终生成BitmapImageViewTarget或者DrawableImageViewTarget,在这两个类中,回调结果会调用view.setImageBitmap(resource)和view.setImageDrawable(resource)。
最后还有一个遗漏,Target的onResourceReady()和onLoadFailed()等一些列方法调用时机在哪、调用者是谁,答案是SingleRequest
,这个类向下执行加载引擎,向上接受请求参数,而且和target有着十分紧密的调用关系,后面篇幅会再回这个类的,这一篇点到为止。
总结
到这时候要做收尾了,在回顾一下这一篇主要讲了哪些点:
Glide
的构建依赖GlideBuilder
,GlideBuilder
可以被用户配置,配置模块可以是Manifest和Annotation;Glide
初始化时会创建Registry
,以及注册相关模块,Registry
是很重要的部分;Glide.with
会创建RequestManager
,RequestManager
通过Fragment
获得生命周期,RequestManager
持有requestTracker
和targetTracker
;RequestManager
通过load()
创建RequestBuilder
对象,RequestBuilder
是Request
的Builder类,主要工作是收集配置信息;RequestBuilder
接收RequestOptions
对象,来丰富配置选项,RequestBuilder
在into()
时创建Request
对象;Request
正真有意义的类是SingleRequest
,SingleRequest
的生命周期被RequestManager
的requestTracker
所接管;SingleRequest
必须得到确切的尺寸才会执行加载引擎逻辑,如果用户没有配置override
,SingleRequest
会从Target
获取尺寸信息,同时它会把Engine
返回的异步结果回调给Target
;Target
主要意义是提供确切的尺寸信息和对结果回调进行处理。Engine
是真是的异步加载调用入口,也是核心逻辑的入口;