Hiten's Blog.

Glide4.8源码拆解(一)基本调用流程

字数统计: 9k阅读时长: 44 min
2019/01/03 Share

前言

Glide是一款功能强大的图片加载框架,它功能强大,用法简单且易于扩展,同时也是Google推荐的Android平台图片加载库,堪称优秀。

本章拆解思路

这算是开篇第一章吧,我准备从入口类和简单的调用流程说起,包括但不限于:

  • Glide的构造
  • RequestManager和生命周期监听
  • Request和配置的收集
  • Target以及触发异步加载

Glide对象初始化

从with()说起

为何要从with()方法,明明初始化代码在get()方法中:

Glide.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
//代码1 判断是否使用清单文件配置模块
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
//代码2 删掉排除的类
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());
}
}

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,具体如何使用清单配置不赘述,借用官方的一个注解配置示例.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
例如,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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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<Class<?>, 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<ParcelFileDescriptor, Bitmap> 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构造方法遇到的比较重要的参数:
enginememoryCachebitmapPoolarrayPoolrequestManagerRetrieverconnectivityMonitorFactorydefaultRequestOptionsdefaultTransitionOptionsregistryglideContext等。
构造环节就讲到这里,下面从with()方法开始,继续往下分析;

with()

上文已经说到with一共有五个重载的方法,最终都调用Glide.getRetriever()方法得到RequestManagerRetriever对象,然后调用RequestManagerRetriever.get()方法,得到RequestManager对象

下面来看一下RequestManagerRetriever的get方法:

RequestManagerRetriever.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class ActivityFragmentLifecycle implements Lifecycle {
private final Set<LifecycleListener> lifecycleListeners =
Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
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

1
2
3
4
5
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}

Lifecycle.java

1
2
3
4
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//实现了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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface ModelTypes<T> {
@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(),支持参数类型:BitmapDrawableStringUriFileIntegerURLbyteObject

它的实现类RequestManager是怎么做具体的实现
RequestManager.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {

public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}

public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}

public RequestBuilder<Drawable> load(@Nullable Uri uri) {
return asDrawable().load(uri);
}

public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}

public RequestBuilder<GifDrawable> asGif() {
return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}

public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
return loadGeneric(drawable)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}

public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
return loadGeneric(uri);
}

public RequestBuilder<TranscodeType> load(@Nullable File file) {
return loadGeneric(file);
}

private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}

public RequestBuilder<TranscodeType> 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

1
2
3
4
5
6
7
8
9
10
public RequestBuilder<TranscodeType> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@NonNull
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null);
}

@NonNull
@Synthetic <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener) {
return into(target, targetListener, getMutableOptions());
}

private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> 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()方法代码量并不大,主要做了这些事:

  1. 创建Request对象,
  2. 将request设置给target
  3. requestManager跟踪request和target;

之前一直在说RequestBuilder,顾名思义RequestBuilder是Request的建造者,Request才是真正的大佬;

Request.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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实现类有三个:
ErrorRequestCoordinatorThumbnailRequestCoordinatorSingleRequest,先不细说Request,回到主流程Request的创建是由Builder类完成,RequestBuilder如何构建Request对象的:

在分析Request构建之前,我觉得有必要写一下Glide缩略图失败新请求的用法:

缩略图 (Thumbnail) 请求

Glide 的 thumbnail() API 允许你指定一个 RequestBuilder 以与你的主请求并行启动。thumbnail() 会在主请求加载过程中展示。如果主请求在缩略图请求之前完成,则缩略图请求中的图像将不会被展示。

1
2
3
4
5
Glide.with(fragment)
.load(url)
.thumbnail(Glide.with(fragment)
.load(thumbnailUrl))
.into(imageView);

thumbnail() 方法有一个简化版本,它只需要一个 sizeMultiplier 参数。如果你只是想为你的加载相同的图片,但尺寸为 View 或 Target 的某个百分比的话特别有用:

1
2
3
4
Glide.with(fragment)
.load(localUri)
.thumbnail(/*sizeMultiplier=*/ 0.25f)
.into(imageView);

在失败时开始新的请求

可以使用 error API 来指定一个 RequestBuilder,以在主请求失败时开始一次新的加载。例如,在请求 primaryUrl 失败后加载 fallbackUrl

1
2
3
4
5
Glide.with(fragment)
.load(primaryUrl)
.error(Glide.with(fragment)
.load(fallbackUrl))
.into(imageView);

如果主请求成功完成,这个error RequestBuilder 将不会被启动。如果你同时指定了一个 thumbnail() 和一个 error() RequestBuilder,则这个后备的 RequestBuilder 将在主请求失败时启动,即使缩略图请求成功也是如此。

以上关于缩略图和fallback大部分内容都是来自Glide官方示例。

RequestBuilder.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private Float thumbSizeMultiplier;
RequestBuilder<TranscodeType> errorBuilder;
private RequestBuilder<TranscodeType> thumbnailBuilder;

public RequestBuilder<TranscodeType> error(@Nullable RequestBuilder<TranscodeType> errorBuilder) {
this.errorBuilder = errorBuilder;
return this;
}

public RequestBuilder<TranscodeType> thumbnail(
@Nullable RequestBuilder<TranscodeType> thumbnailRequest) {
this.thumbnailBuilder = thumbnailRequest;

return this;
}

public RequestBuilder<TranscodeType> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions);
}

private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> 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<TranscodeType> target,
RequestListener<TranscodeType> 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<TranscodeType> target,
RequestListener<TranscodeType> 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逻辑

  1. 判断用户是否设置过errorRequest,没有的话直接创建带有缩略图的mainRequest(不一定真的有缩略图);
  2. 如果设置过errorRequest,拿errorRequest对象调用buildRequestRecursive,创建errorRequest请求
  3. 用ErrorRequestCoordinator包装errorRequest和mainRequest。

再判断thumbnailRequest逻辑

  1. 如果用户设置了thumbnailBuilder,取配置参数,创建fullRequest和thumbRequest,然后用ThumbnailRequestCoordinator包装返回;
  2. 如果用户设置了thumbSizeMultiplier,创建fullRequest和thumbRequest,然后用ThumbnailRequestCoordinator包装返回;
  3. 用户没有缩略图,只创fullRequest;

ps:

其中fullRequest和mainRequest表示原始的请求,thumbRequest表示缩略图请求,errorRequest表示错误重使请求;

如果用户同时设置了error和thumbnail,最终生成的模型应该是ErrorRequestCoordinator(ThumbnailRequestCoordinator(fullRequest,thumbRequest),errorRequest);

值得注意到是,以Coordinator结尾的连个Request类并不执行真的的Request逻辑,真正执行逻辑的类是SingleRequest

SingleRequest分析

接下来就是SingleRequest咯,相关代码:

SingleRequest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public final class SingleRequest<R> 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

1
2
3
4
5
6
7
8
9
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,这一点在下面代码可以说明;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public ViewTarget<ImageView, TranscodeType> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface Target<R> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public abstract class SimpleTarget<Z> extends BaseTarget<Z> {
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
public abstract class CustomViewTarget<T extends View, Z> implements Target<Z> {
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<SizeReadyCallback> 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<SizeDeterminer> 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
}

最终生成BitmapImageViewTarget或者DrawableImageViewTarget,在这两个类中,回调结果会调用view.setImageBitmap(resource)和view.setImageDrawable(resource)。

最后还有一个遗漏,Target的onResourceReady()和onLoadFailed()等一些列方法调用时机在哪、调用者是谁,答案是SingleRequest,这个类向下执行加载引擎,向上接受请求参数,而且和target有着十分紧密的调用关系,后面篇幅会再回这个类的,这一篇点到为止。

总结

到这时候要做收尾了,在回顾一下这一篇主要讲了哪些点:

  1. Glide的构建依赖GlideBuilder,GlideBuilder可以被用户配置,配置模块可以是Manifest和Annotation;
  2. Glide初始化时会创建Registry,以及注册相关模块,Registry是很重要的部分;
  3. Glide.with会创建RequestManagerRequestManager通过Fragment获得生命周期,RequestManager持有requestTrackertargetTracker;
  4. RequestManager通过load()创建RequestBuilder对象,RequestBuilderRequest的Builder类,主要工作是收集配置信息;
  5. RequestBuilder接收RequestOptions对象,来丰富配置选项,RequestBuilderinto()时创建Request对象;
  6. Request正真有意义的类是SingleRequest,SingleRequest的生命周期被RequestManagerrequestTracker所接管;
  7. SingleRequest必须得到确切的尺寸才会执行加载引擎逻辑,如果用户没有配置overrideSingleRequest会从Target获取尺寸信息,同时它会把Engine返回的异步结果回调给Target;
  8. Target主要意义是提供确切的尺寸信息和对结果回调进行处理。
  9. Engine是真是的异步加载调用入口,也是核心逻辑的入口;
CATALOG
  1. 1. 前言
  2. 2. 本章拆解思路
  3. 3. Glide对象初始化
    1. 3.1. 从with()说起
    2. 3.2. 解析注解配置项
    3. 3.3. GlideBuilder创建默认参数
    4. 3.4. 构造方法和创建Registry
  4. 4. with()
  5. 5. load()
  6. 6. apply()
    1. 6.1. RequestOptions标志位
  7. 7. into()流程
    1. 7.1. 缩略图 (Thumbnail) 请求
    2. 7.2. 在失败时开始新的请求
    3. 7.3. 构建Request流程
    4. 7.4. 构建嵌套Request核心流程
    5. 7.5. SingleRequest分析
    6. 7.6. SingleRequest尺寸问题
    7. 7.7. Target是接口
    8. 7.8. Target计算尺寸
      1. 7.8.1. SimpleTarget获取尺寸
      2. 7.8.2. CustomViewTarget获取尺寸
  8. 8. 总结