Glide4.11源码分析(一)生命周期的绑定
Glide4.11源码分析(二)三级缓存之内存缓存
Glide4.11源码分析(三)子线程执行的那些事儿及本地缓存
前言
Glide库是一个优秀图片下载、展示、剪裁等功能于一体的开源库,开发中经常会用到,但是这么优秀的开源库,内部到底是什么逻辑实现的呢?今天就一起来看一看他的真面目。
基本使用
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.glide_activity_layout);
imageView = ((ImageView) findViewById(R.id.img));
RequestManager requestManager = Glide.with(this);
RequestBuilder<Drawable> builder = requestManager.load("http://dmimg.5054399.com/allimg/pkm/pk/22.jpg");
//拷贝一个builder,包括他的一些配置都会被拷贝进来,从而不影响原builder
// builder = builder.autoClone();
builder = builder.placeholder(R.mipmap.ic_launcher);
builder = builder.error(R.mipmap.ic_launcher_round);
builder = builder.centerCrop();
// builder = builder.diskCacheStrategy(DiskCacheStrategy.ALL);
builder.into(imageView);
}
这是最基本的使用方式,不过有时候我们需要扩展Glide 的API,而且可能在很多地方都会使用扩展后的Glide加载图片,那总不能没次使用的时候单独扩展吧。所以引出了另外一种使用方式
//创建类继承自AppGlideModule并用@GlideModule进行注解
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
super.applyOptions(context, builder);
//扩展修改MemoryCache
builder.setMemoryCache(new MySelfMemoryCache());
builder.setSourceExecutor(GlideExecutor.newSourceExecutor());
builder.setAnimationExecutor(GlideExecutor.newAnimationExecutor());
}
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide,
@NonNull Registry registry) {
//将默认的网络请求方式(URLConnection)改为OkHttp
registry.replace(GlideUrl.class, InputStream.class,new OKHttpUrlLoader.Factory());
}
}
//自定义的MySelfMemoryCache和OKHttpUrlLoader类的代码不贴了,参照系统的写就行
//使用的时候可以这样使用
//GlideApp是注解为我们自动生成的
GlideApp.with(this)
.load("http://dmimg.5054399.com/allimg/pkm/pk/22.jpg")
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher_round)
.fitCenter()
.into(imageView);
看下我写的okhttpfetcher打印的log
2021-03-25 22:57:05.781 21206-21294/com.source.test D/OkHttpUrlFetcher: OkHttpUrlFetcher: 构造方法
2021-03-25 22:57:05.782 21206-21294/com.source.test D/OkHttpUrlFetcher: OkHttpUrlFetcher: 构造方法
2021-03-25 22:57:05.829 21206-21301/com.source.test D/OkHttpUrlFetcher: loadData: 我要开始loaddata了
以上就是Glide4.11的使用方式,很灵活很方便。开始逐一分析,我们以第一种使用方式的形式去分析,分析的是首次加载图片的过程。
源码分析
很明显使用的时候就是链式调用,使用了建造者模式,使用起来很方便,我们就按着调用的顺序去逐一分析每一步调用做了什么工作。先来看Glide.with(this)
> 代码片段1
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
这个方法就是通过Activity获取一个RequestManager
,这个RequestManager
就是负责管理和启动Glide请求的。可以通过Activity、Fragment等生命周期事件开启、停止或重启请求。至于他们怎么绑定到一起的,接着往下看,先看getRetriever(activity)
方法
> 代码片段2
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
//双重检查单例模式获取Glide实例对象
public static Glide get(@NonNull Context context) {
if (glide == null) {
//注释1
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
注释1处是通过反射获取由编译时注解生成的GeneratedAppGlideModuleImpl
。我们可以通过注解来定义GlideBuilder
的全局属性,注解会生成GeneratedAppGlideModuleImpl
,而注释1就是通过反射获取GeneratedAppGlideModuleImpl
实例,进而拿到我们设置的全局属性。之后就调用checkAndInitializeGlide
,最终来到了initializeGlide()
方法
> 代码片段3
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder,@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
//.....略......省略处的逻辑是通过解析Manifest.xml文件,获取GlideModule,这种方式已经不鼓励使用了
//注释2
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
builder.setRequestManagerFactory(factory);
//....略....
if (annotationGeneratedModule != null) {
//这里的builder是通过new GlideBuilder生成的,这里就调用到我们写的注解的地方了,会给GlideBuilder对象设置一些线程池,内存缓存方式等内容
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//注释3
Glide glide = builder.build(applicationContext);
//...略...
if (annotationGeneratedModule != null) {
//用于注册一些组件,这些组件包括 解码流、解析exif的方向的组件
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
//Glide 类实现了ComponentCallbacks2接口,在此注册回调接口 这个接口回调用于内存管理的
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
注释2 的意思如果使用了注解,则会通过注解生成的annotationGeneratedModule
的getRequestManagerFactory()
获取RequestManagerFactory
,而注解生成的类GeneratedAppGlideModuleImpl
的getRequestManagerFactory
中直接new GeneratedRequestManagerFactory()
,这个factory会在build方法中生成一个GlideRequests
对象。这对象继承了RequestManager
。如果没有使用注解,那factory就是null。
下面先看注释3出的方法调用
> 代码片段4
com.bumptech.glide.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对象,这里创建的Engined对象中有个成员变量engineJobFactory是EngineJobFactory类型的,后面用的到
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//这里创建RequestManagerRetriever,参数requestManagerFactory就是代码片段3注释2中
//通过调用builder.setRequestManagerFactory(factory)传进来的;
//这个factory要么是null要么就是GeneratedRequestManagerFactory对象。
//RequestManagerRetriever的构造方法中判断factory如果为null,
//就会为factory赋一个默认对象,详情见下面的方法
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
看下new RequestManagerRetriever
这句代码中判断factory是null的话就会使用DEFAULT_FACTORY对象,这是默认的factory ,他的build方法直接new了一个RequestManager
。
上面设置了一系列的成员变量,最终new了一个Glide出来。下面以表格形式说明这些成员变量的用途。
说明:GlideExecutor就是线程池的代理类,内部通过建造者模式创建不同类型的ThreadPoolExecutor的代理类,来实现线程池的功能。
对象 | 所属类型 | 说明 | 用途 |
---|---|---|---|
sourceExecutor | GlideExecutor | 此线程池的核心线程数和最大线程数相等,值为4或者设备的内核数 | 执行网络请求的线程池。 |
diskCacheExecutor | GlideExecutor | 不可以进行网络请求。此线程池的核心线程数和最大线程数均为1 | 执行硬盘缓存线程池 |
animationExecutor | GlideExecutor | 不允许网络请求。此线程池的核心线程数和最大线程数相等,当sourceExecutor线程数大于4的时候,此线程池线程数为2,否则就是1 | 执行动画的线程池 |
memorySizeCalculator | MemorySizeCalculator | 缓存计算器。根据设备的像素密度和屏幕宽高等信息计算并设置缓存大小 | |
connectivityMonitorFactory | DefaultConnectivityMonitorFactory | ConnectivityMonitor的工厂类,ConnectivityMonitor类是用来管理网络连接断开情况,而DefaultConnectivityMonitorFactory类根据APP是否有permission.ACCESS_NETWORK_STATE 权限来分别创建DefaultConnectivityMonitor和NullConnectivityMonitor 类 | |
bitmapPool | BitmapPool | 根据bitmapPoolSize大小,使用不同缓存技术。而bitmapPoolSize又是MemorySizeCalculator根据屏幕像素位数及设备APP的分配的内存大小决定的。1、如果bitmapPoolSize大于0 ,缓存池就是LruBitmapPool,而LruBitmapPool缓存策略分两种,a)、设备SDK版本大于19,使用SizeConfigStrategy缓存策略类:即缓存key是通过图片的config(通过bitma.getConfig方法获取)和图片的byte大小(通过Bitmap.getAllocationByteCount方法获取)生成的;b)、设备SDK版本小于19,使用AttributeStrategy缓存策略类:即缓存key是通过图片的宽、高和config生成的。2、如果bitmapPoolSize不大于0,缓存池就是BitmapPoolAdapter,这个其实就不是缓存池,因为他的get方法就是创建一个图片,而put方法就是回收图片 | 用做Bitmap对象的复用 |
arrayPool | LruArrayPool | 数组池,缓存用,池大小是固定的,回收策略采用的是Lru缓存策略 | |
memoryCache | LruResourceCache | 内存缓存池,采用LRU缓存策略 | 缓存已经完成解析的资源 |
diskCacheFactory | InternalCacheDiskCacheFactory | 磁盘缓存工厂类,磁盘缓存采用了文件快照存储的方式,会生成一个名字journal的日志文件,保存了缓存的相关信息。每条缓存的键是都是固定数量的字符串,值就是字节序列,能够直接读取流或者作为文件系统访问 | 创建DiskLruCache |
engine | Engine | 真正负责加载资源并管理活动的或缓存资源的引擎类 | |
defaultRequestListeners | RequestListener | RequestListener集合 | |
requestManagerRetriever | RequestManagerRetriever | 此类实现了Handler.Callback接口,内部有大都是静态方法 | 获取或者创建RequestManager的类 |
以上表格中展示的就是此方法中设置的成员变量的类型及相关说明,这些变量都会用来作为接下来要new的 Glide的参数,后续加载、缓存图片的时候会用到。
Glide的构造方法有一百多行代码,Glide构造方法主要做的工作就是设置成员变量,创建了一个注册表Registry(相当于glide的大管家,管理Glide加载图片的方式,编解码等功能)和GlideContext对象(它是Glide中所有加载的全局上下文,其中包含并公开了加载资源所需的各种注册表和类)。
到此只是分析了代码片段2
中第一个方法里的代码return Glide.get(context).getRequestManagerRetriever();
中的前半部分,Glide对象已经生成了,所以这句代码的后半部分调用了Glide类的getRequestManagerRetriever
方法获取到RequestManagerRetriever
对象。接着回到代码片段1
中看return getRetriever(activity).get(activity);
这句代码的后半部分,也就是RequestManagerRetriever
类的get(Activity activity)
方法。
> 代码片段5
@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));
}
}
这里会区分是否是在后台线程和主线程,如果Glide是在后台线程使用,则传递的是ApplicationContext,否则传的的是Activity对象。先看下第一种情况,这种情况会最终调用下面代码
> 代码片段6
private RequestManager getApplicationManager(@NonNull Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
//强制使用ApplicationLifecycle来接管RequestManager的生命周期
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context.getApplicationContext());
applicationManager =
factory.build(
glide,
new ApplicationLifecycle(),
new EmptyRequestManagerTreeNode(),
context.getApplicationContext());
}
}
}
return applicationManager;
}
如果使用注解的话,factory就是注解自动生成的,是由注解自动创建GeneratedRequestManagerFactory
的对象,否则factory就是默认的RequestManagerFactory
对象,然后factory调用build方法,将ApplicationLifecycle、getApplicationContext等作为参数调用RequestManager的构造方法。接下来看代码片段5
的第二种情况,在主线程使用Glide加载图片。
> 代码片段7
@NonNull
private RequestManager fragmentGet(@NonNull Context context,@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,boolean isParentVisible) {
//注释4
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
//注释4.1
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
我们来看下是如何将Fragment的生命周期和请求绑定的。方法fragmentGet
很好理解,注释4出现调用getRequestManagerFragment
,获取一个RequestManagerFragment,那就先看看RequestManagerFragment
方法是怎么取的,getRequestManagerFragment
方法中先用FragmentManager
通过Tag FRAGMENT_TAG
来找Fragment,如果找不到就通过pendingRequestManagerFragments缓存去找,如果还找不到就new一个然后存储下来并返回。RequestManagerFragment的构造方法中会创建ActivityFragmentLifecycle
对象并赋值给成员变量lifecycle
,可参考下面代码片段8
。返回之后接着看fragmentGet
后续工作,看注释4.1处,会生成requestManager
对象,并将RequestManagerFragment
中的lifecycle
作为参数传进build方法中,并且将requestManager
对象设置给RequestManagerFragment
。
那么RequestManagerFragment是个什么东西?其实这里是用Fragment的生命周期来绑定请求的生命周期的
> 代码片段8
//RequestManagerFragment就是一个没有view的空Fragment,它持有RequestManager对象引用,和ActivityFragmentLifecycle对象引用
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
@Nullable private RequestManager requestManager;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
//生命周期回调,同时调用成员变量lifecycle的生命周期
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
//...略...
}
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();
}
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStop();
}
}
//略。。。
}
上面代码第二段是ActivityFragmentLifecycle
。RequestManagerFragment生命周期调用的时候就会调用ActivityFragmentLifecycle的onStart、onStop等方法,这些方法中会遍历集合lifecycleListeners
,并调用集合里监听对象响应的方法。集合中的这些对象是通过调用ActivityFragmentLifecycle
对象的addListener
方法加进去的。这里先标记一下。待会就能看到这个addListener
是什么时候加入的。
现在返回代码代码片段7
中的注释4.1
,这里的factory的来历已经在代码片段3注释2
和代码片段4
中解释了。调用factory的build方法,这里我们看默认factoryDEFAULT_FACTORY
中的build方法,该方法直接new了一个RequestManager
对象,看下构造方法
>代码片段8.1
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
//注释4.2
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
构造方法的第二个参数lifecycle就前面获取的RequestManagerFragment
对象的成员变量lifecycle
也就是ActivityFragmentLifecycle
类型的对象,看上面代码中注释4.2
调用了lifecycle.addListener(this)
,结合上文中加粗的标记的地方,也就是这里先标记一下
那个文字的地方,由于RequestManager实现了LifecycleListener
,所以此时RequestManagerFragment的生命周期方法已经和RequestManager生命周期方法绑定了。
结论:RequestManagerFragment
的生命周期方法onStart、onStop、onDestory
调用的时候,RequestManager
的相对应的生命周期方法也将得到回调。
先看下RequestManager
的onStart、onStop方法干了啥
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
看上去好像是加载了请求。这部分下篇文章再讲。