Glide源码分析之Glide和RequestManager构建过程
Glide源码分析之自定义模块及Glide如何触发网络请求(未发布)
Glide源码分析之load(url)和into(iv)(未发布)
Glide源码分析之缓存机制(未发布)
基本用法
多数情况下,使用Glide加载图片非常简单,一行代码足矣:
Glide.with(fragment).load(myUrl).into(imageView)
取消加载:
Glide.with(fragment).clear(imageView);
实际上,Glide.with() 中传入的 Activity 或 Fragment 实例销毁时,Glide 会自动观察 Activity 或 Fragment 的生命周期取消加载并回收资源,实际上Glide为了监听Activity 或 Fragment的声明周期会在内部添加一个fragment就是为监听生命周期。
看一下Glide.with()的源码:
/**
* with方法主要的逻辑:
* 1、在1步骤中通过getRetriever获取到在初始化Glide时创建的RequestManagerRetriever实例;
* 2、在2步骤中通过RequestManagerRetriever的get方法获取RequestManager实例。
*
*
* RequestManagerRetriever用于创建新的RequestManagers或从activity和fragment中检索现有的RequestManagers
*
* @param context
* @return
*/
@NonNull
public static RequestManager with(@NonNull Context context) {
// 调用getRetriever获取RequestManagerRetriever
RequestManagerRetriever requestManagerRetriever = getRetriever(context);// 1
// 调用RequestManagerRetriever的get方法,获取RequestManager(图片请求加载管理者)
RequestManager requestManager = requestManagerRetriever.get(context); // 2
return requestManager;
}
/**
* 请求资源使用Activityh生命周期同步
*
* @param activity
* @return
*/
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
/**
* 请求资源使用FragmentActivity生命周期同步
*/
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
/**
* 请求资源使用Fragment生命周期同步
*/
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/**
* 请求资源使用android.app.Fragment生命周期同步
*/
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/**
* 通过View去搜索其依附的Activity或者Fragment并使用它们作为请求资源使用生命周期同步
*/
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
可以看到Glide.with(context)有几个重载的方法,Glide.with(context)方法主要的逻辑:
1、在1步骤中通过getRetriever获取到在初始化Glide时创建的RequestManagerRetriever实例;
2、在2步骤中通过RequestManagerRetriever的get方法获取RequestManager实例。 RequestManagerRetriever用于创建新的RequestManagers或从activity和fragment中检索现有的RequestManagers
Glide.with(context)最终调用getRetriever(context),然后再调用RequestManagerRetriever的实例get()方法,去获取RequestManager对象:
/**
* getRetriever方法主要逻辑:
* 1、在1步骤,会创建Glide实例并且初始化Glide实例,还会创建RequestManagerRetriever实例对象;
* 2、在2步骤直接返回RequestManagerRetriever实例
*
* @param context
* @return
*/
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) { // 1.2
// Glide.get(context) 获取Glide对象,包括初始化之类的配置
Glide glide = Glide.get(context);//1
// 通过Glide获取RequestManagerRetriever
// 可能你会惊讶在哪 初始化RequestManagerRetriever的,其实是在GlideBuilder的build方法中
RequestManagerRetriever requestManagerRetriever = glide.getRequestManagerRetriever();// 2
return requestManagerRetriever;
}
1、 Glide.get(context) 获取Glide对象包括初始化之类的配置,初始化后面会讲GlideBiulder;
2、通过Glide对象获取RequestManagerRetriever, 可能你会惊讶在哪 初始化RequestManagerRetriever的,其实是在GlideBuilder的build方法中。
接下来看一下调用RequestManagerRetriever 的get方法,也是有几个重载;
/**
*
* 上面getRetriever(context)方法,主要是构建Glide和RequestManagerRetriever
*
* RequestManagerRetriever:一组静态方法,用于创建新的RequestManagers或从活动和片段中检索现有的RequestManagers。
*
* 这一步就是构建RequestManager:描述图片加载请求管理者
*
*
* 作用:主要是通过传入的context构建RequestManager实例,当然你这里可会从activity和fragment中获取已经存在的RequestManager
* 为什么需要context?主要是构建的RequestManager即请求管理,需要感知各组件的生命周期,例如:application、activity和fragment
*
* 主要的逻辑:
* 1、在1步骤中判断是否是在主线程和是不是Application,如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理
* 2、在2步骤中直接当成Application处理;
* 3、最后会通过RequestManager工厂(RequestManagerFactory)创建RequestManager实例
*
* 最后:
* 虽然get方法有多个重载其实逻辑的处理只有两种:
* 1、传入的context是非Application参数的情况:
* 不管是传入的context是Activity、FragmentActivity、v4包下的Fragment、还是app包下的Fragment,
* 最终的逻辑是一样的,会向当前的Activity当中添加一个隐藏的Fragment。因为Glide需要感知加载的生命周期
* 2、传入的context是Application参数的情况,或者是在后台线程:
* 如果传入的context是Application或者是在后台线程,直接就调用getApplicationManager()方法来获取一个RequestManager对象
*
*
*
*
* 注意这里的get方法都是单例的
*
* @param context
* @return
*/
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
//如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理
} else if (Util.isOnMainThread() && !(context instanceof Application)) {//1
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);// 2
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
// 获取当前activity的FragmentManager,因为你需要为当前activity添加隐藏的fragment
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null, isActivityVisible(activity));
}
}
@NonNull
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);
}
1、上面getRetriever(context)方法,主要是构建Glide和RequestManagerRetriever
2、RequestManagerRetriever:一组静态方法,用于创建新的RequestManagers或从活动和片段中检索现有的RequestManagers。
3、这一步就是构建RequestManager:描述图片加载请求管理者
4、 作用:主要是通过传入的context构建RequestManager实例,当然你这里可会从activity和fragment中获取已经存在的RequestManager
5、为什么需要context?主要是构建的RequestManager即请求管理,需要感知各组件的生命周期,例如:application、activity和fragment
6、主要的逻辑:
- 在1步骤中判断是否是在主线程和是不是Application,如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理
- 在2步骤中直接当成Application处理;
- 最后会通过RequestManager工厂(RequestManagerFactory)创建RequestManager实例
最后:虽然get方法有多个重载其实逻辑的处理只有两种:传入的context是非Application参数的情况:不管是传入的context是Activity、FragmentActivity、v4包下的Fragment、还是app包下的Fragment,最终的逻辑是一样的,会向当前的Activity当中添加一个隐藏的Fragment。因为Glide需要感知加载的生命周期,
传入的context是Application参数的情况,或者是在后台线程:
如果传入的context是Application或者是在后台线程,直接就调用getApplicationManager()方法来获取一个RequestManager对象
注意这里的get方法都是单例的
可以看到在get方法中通过supportFragmentGet方法和getSupportRequestManagerFragment构建隐藏的fragment:
/**
* 主要逻辑:
* 1、搜索是否已经添加了隐藏的Fragment到当前的Activity中,如果已经添加过了是由缓存的。
* 2、如果在当前activity,已经添加了隐藏的Fragment,就尝试从隐藏的Fragment中搜索RequestManager,
* 如果没有找到,就调用RequestManager工厂创建一个RequestManager,并添加到隐藏的Fragment中,然后返回RequestManager实例。
*
* 注意:其实一个Activity就存在一个RequestManager,它们的关系是activity-SupportRequestManagerFragment-RequestManager一一对应
*
* @param context
* @param fm
* @param parentHint
* @param isParentVisible
* @return
*/
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
@Nullable Fragment parentHint, boolean isParentVisible) {
// 搜索隐藏的Fragment
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
//从隐藏的Fragment搜索RequestManager
RequestManager requestManager = current.getRequestManager();
// 如果不存在就直接创建RequestManager并添加到隐藏的Fragment中缓存
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(@NonNull final FragmentManager fm,
@Nullable Fragment parentHint, boolean isParentVisible) {
// 搜索是否已经添加了隐藏的Fragment
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);//1
if (current == null) {
// 从缓存中找
current = pendingSupportRequestManagerFragments.get(fm);// 2
// 还是没有找到,就直接创建一个Fragment
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
// 如果当前activity正在显示
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
// 加入缓存
pendingSupportRequestManagerFragments.put(fm, current);
// 开始fragment事务,标志设置为FRAGMENT_TAG
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
1、搜索是否已经添加了隐藏的Fragment到当前的Activity中,如果已经添加过了是由缓存的。
2、如果在当前activity,已经添加了隐藏的Fragment,就尝试从隐藏的Fragment中搜索RequestManager, 如果没有找到,就调用RequestManager工厂创建一个RequestManager,并添加到隐藏的Fragment中,然后返回RequestManager实例。 注意:其实一个Activity就存在一个RequestManager,它们的关系是activity-SupportRequestManagerFragment-RequestManager一一对应。
为什么需要使用pendingRequestManagerFragments?
为什么需要使用pendingRequestManagerFragments这样一个集合来临时存储一下fragment,然后又马上通过handler发送消息移除?这其实是跟主线程的Looper机制和Fragment的事务机制有关的,Fragment事务也是通过Handler处理的。我们知道,android中的主线程是一个闭环,通过Handler发送消息到MessageQueue,然后通过Looper轮询获取消息并交给Handler处理,我们来看如下常见场景,这里所说的是在线程中,如果是子线程,那么不会有添加Fragment这一步,也就是放弃监听生命周期。
Glide.with(this).load(url_1).into(mImageView_1);//1
Glide.with(this).load(url_2).into(mImageView_2);//2
看看这两行代码的Handler消息处理图
当我们执行注释1代码时:fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
时对应m1,执行handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
以此类推,但是Handler中MessageQueue是同步取出Message处理,它一般会先执行m1-->r1 -->m2 -->r2,所以Glide为了保证RootFragment的唯一性,加上临时缓存,上面两行代码时同步执行,当第一行执行完那么缓存中必然存在rootfragment。
到此为止就已经创建你好RequestManager了,也就是Glide的整个构建流程完毕,有的读者可能会发现Glide的构建怎么没有,下面就开始。
大家还记得 getRetriever(context)方法中有这么一行
Glide glide = Glide.get(context);
我们来看看Glide get(@NonNull Context context)源码
private static volatile Glide glide;
/**
* Get the singleton.
* 单例双重校验
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
这个方法首先会检查是否已经初始化了,因为在初始化Glide的线程中,一个或多个类可以多次调用Glide.get(context)。
如果没有这个检查,那些调用可能会触发无限递归。就是避免重复初始化Glide对象
下面就是Glide初始化真正的逻辑:
/**
* 首先找到@GlideModel注解生成的类GeneratedAppGlideModuleImpl
*
* @param context
* @param builder
*/
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
//获取 applicationContext
Context applicationContext = context.getApplicationContext();
// 找到@GlideModel注解生成的类如GeneratedAppGlideModuleImpl
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
/**
*
*
* 会触发每个Module包括我们自定义的Module中的applyOptions
*
* 在GlideBuilder中的biuld方法,每一个默认配置都是判断null,所以我们可以在我们的自定义Module中修改Glide的配置
*
*/
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
// 构建Glide
Glide glide = builder.build(applicationContext);
// 注册组件,例如:替换默认HttpUrlConnection为OkHttp以及其他组件,当然这些是可以通过注解来完成的,详细请看官方的demo
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
首先找到@GlideModel注解生成的类GeneratedAppGlideModuleImpl,并且会触发每个Module包括我们自定义的Module中的applyOptions,以便我们修改Glide的默认配置。也就是说当你调用with方法时,就已经初始化Glide
再看看initializeGlide方法中初始化相关的配置GlideBiulder,这里使用构建模式
// 构建Glide
Glide glide = builder.build(applicationContext);
GlideBuilder:
private final Map, TransitionOptions, ?>> defaultTransitionOptions = new ArrayMap<>();
// 负责启动负载并管理活动和缓存资源。
private Engine engine;
// Bitmap 复用池(享元模式)
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
// 内存管理计算器或者策略
private MemorySizeCalculator memorySizeCalculator;
private MemoryCache memoryCache;
// Glide 资源线程池
private GlideExecutor sourceExecutor;
// 磁盘缓存线程池
private GlideExecutor diskCacheExecutor;
// 磁盘缓存工厂
private DiskCache.Factory diskCacheFactory;
// 网络状态监视器工厂
private ConnectivityMonitorFactory connectivityMonitorFactory;
private int logLevel = Log.INFO;
// 默认请求项
private RequestOptions defaultRequestOptions = new RequestOptions();
@Nullable
private RequestManagerFactory requestManagerFactory;
//执行动画的线程池
private GlideExecutor animationExecutor;
private boolean isActiveResourceRetentionAllowed;
@Nullable
private List> defaultRequestListeners;
private boolean isLoggingRequestOriginsEnabled;
出了这些成员变量之外还有就是这些变量的setxx方法,我就不一一列出来,重点看看biuld方法。
/**
* 其实每次判断是否为null就是不应该重复初始化,这也给我们在自定义Model修改Glide的默认配置
*
* @param context
* @return
*/
@NonNull
Glide build(@NonNull Context context) {
// 网络资源操作线程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 磁盘缓存操作线程池,不允许进行网络操作
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 执行动画操作线程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//内存计算器,它尝试根据某些常量和设备屏幕密度,宽度和高度智能地确定给定设备的高速缓存大小。
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
// 设备网络监视器
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
// bitmap 复用池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
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(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//一组静态方法,用于创建新的RequestManagers或从活动和片段中(Retriever)检索现有的RequestManager。
// RequestManager 描述图片加载请求管理者,例如:感知声明周期取消请求
RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);
// 创建GLide对象
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
其实Glide的构建是相当复杂的,包括各种线程池的配置以及各种复用池的构建,通过GlideBuilder构建Glide,RequestManager见名思意就是检索RequestManager即在activity或者Fragment中检索是否存在,否则直接创建。