Glide
是一个开源的图片处理库,源代码的学习对于我们的帮助是非常大的,不过要看源码项目总得有个流程,这里我就从Glide.with(FragmentActivity).load(URL).apply(centerCropTransform()) .into(imageViewRes);
作为阅读流程,首先就从with(FragmentActivity)
开始开始吧。(PS:本人阅读的源码为 Glide 4.7 版本)
首先来看下面的 with
方法的流程时序图:
接着就来依据这个时序图来阅读以下 Glide
的源码吧。
Step1 Glide.with(FragmentActivity)
/**
* 传入FragmentActivity对象来启动Glide并绑定FragmentActivity的生命周期,设置默认配置
*
* @param FragmentActivity 当前绑定的FragmentActivity
* @return 绑定了当前activity的RequestManager, 可调用load方法加载数据
*/
@NonNull
public static RequestManager with(@NonNull FragmentActivity fragmentActivity) {
return getRetriever(activity).get(activity);
}
调用当前类的 getRetriever
方法。
Step2 Glide.getRetriever(Context)
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
//空指针检查,context为null则直接抛出空指针异常
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();
}
Preconditions
这里并非 support v4 里面的那个 Preconditions
工具类, 因为后者存在着使用限制,因此 Glide
里面就直接把它需要的代码拷贝过来使用了:
/**
* 这里是复制v4包的内部参数检查工具类,主要是检查参数是否正常,不正常就抛出异常确保外部今早发现问题
* 个人猜测是因为v4包里面的Preconditions工具类存在某些使用限制,这里才直接复制出来
*/
public final class Preconditions {
//代码省略
}
Step3 Glide.get(Context)
/**
* volatile确保内存可见性,进一步确保单例
*/
private static volatile Glide glide;
//..........
/**
* 生成或获取Glide的单例对象
*
* @return 单例对象
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
Step4 Glide.checkAndInitializeGlide(Context)
/**
* volatile确保内存可见性,进一步确保单例
*/
private static volatile boolean isInitializing;
private static void checkAndInitializeGlide(Context context) {
// 在Glide初始化的过程中,可能会多次调用Glide.get(context)
// 为避免多次初始化,这里加了一个检查判断,确保Glide对象为单例
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
Step4 Glide.initializeGlide()
/**
* Glide的初始化方法
*
* @param context 上下文
*/
private static void initializeGlide(Context context) {
initializeGlide(context, new GlideBuilder());
}
这里创建一个 GlideBuilder
对象,它是一个用于设置 Glide
默认配置的构建者类:
/**
* 用于设置Glide默认配置使用的构建者类
*/
public final class GlideBuilder {
/**
* 图片变换处理的Map集合
* 图片变化处理就是指圆角图片之类的处理
*/
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
/**
* 负责启动并管理缓存资源活动的工具类
*/
private Engine engine;
/**
* Lru策略的图片池,内存不足时自动清空
*/
private BitmapPool bitmapPool;
/**
* Lru策略的数组池,用于读写IO,内存不足时自动清空
*/
private ArrayPool arrayPool;
/**
* Lru策略的内存缓存池,内存不足时自动清空
*/
private MemoryCache memoryCache;
/**
* 线程池,用于查找内存缓存,最大线程数为4,具体取决于cpu
*/
private GlideExecutor sourceExecutor;
/**
* 线程池,用于查找本地磁盘缓存,最大线程数为4,具体取决于cpu
*/
private GlideExecutor diskCacheExecutor;
/**
* 用于创建本地磁盘缓存对象的工厂
* 默认本地磁盘缓存size为250M
*/
private DiskCache.Factory diskCacheFactory;
/**
* 缓存配置工具类,它通过获取手机硬件常量和手机的屏幕密度、宽度和长度来计算出最适合当前情况的缓存配置
*/
private MemorySizeCalculator memorySizeCalculator;
/**
* 用于生产网络状态监听事件的工厂
*/
private ConnectivityMonitorFactory connectivityMonitorFactory;
/**
* 设置Glide的log打印等级
*/
private int logLevel = Log.INFO;
/**
* 设置Glide的配置选项
*/
private RequestOptions defaultRequestOptions = new RequestOptions();
/**
* 用于创建RequestManager对象的工厂
*/
@Nullable
private RequestManagerFactory requestManagerFactory;
/**
* 线程池,用于加载gif图片,默认线程数为1~2,最大数取决于cpu的核数
*/
private GlideExecutor animationExecutor;
/**
* 是否将保留图片资源数据不给回收,默认为false
* 需要注意的是,设为true将会导致更大的内存消耗,增加crash的几率
*/
private boolean isActiveResourceRetentionAllowed;
//.....
//构成完成 Glide对象
public Glide build(Context context) {
//.....
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
}
可以看到,Glide
的初始化其实就是 GlideBuilder
来完成的。下面就是 Glide
完成实例的过程了:
private static void initializeGlide(Context context, GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List<GlideModule> manifestModules = Collections.emptyList();
//如果没有注解生成的Module就去读取清单文件,检查是否有module
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
//如果有注解生成的Module就对比一下清单文件获取的module
//删除相同的module
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
Iterator<GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
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();
}
}
//打印出从清单文件中获取到的有效module
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
//初始化请求工厂
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
for (GlideModule module : manifestModules) {
//回调给外层调用者提供GlideBuilder来修改默认配置
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
//如果有注解生成的Module
//回调给外层调用者提供GlideBuilder来修改默认配置
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
Glide glide = builder.build(applicationContext);
for (GlideModule module : manifestModules) {
//回调给外层调用者提供registry工厂管理类来修改默认配置
module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {
//如果有注解生成的Module
//回调给外层调用者提供registry工厂管理类来修改默认配置
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
//监听App的内存变化,内存紧张时把BitmapPool、MemoryCache和ArrayPool都清空
applicationContext.registerComponentCallbacks(glide);
//完成单例的实例化
Glide.glide = glide;
}
关于 Glide
设置外层的 Module
来修改一些默认配置,这类在网上已经有很多资源了,这里就不多说什么了。
如果想搞明白 Glide
如何通过清单文件加载 Molude
可以看这篇 blog 。
Step5 Glide.getRequestManagerRetriever()
/**
* @return 返回一个RequestManager的管理工具类
*/
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
RequestManagerRetriever
是 Handler.CallBack
实现类,同时也是生命周期的一个管理类:
/**
* 一个生成或获取RequestManager的管理工具类
* 它可以从绑定的Activity或Fragment中接收存在的RequestManager对象
* 同时在RequestManager上面获取存在的感知外层生命周期的Fragment
* 如果不存在该对象,就生成一个新的RequestManager
* 在生成新的RequestManager同时也生成感知外层生命周期的Fragment
*/
public class RequestManagerRetriever implements Handler.Callback {
//代码暂时省略
}
Step6 RequestManagerRetriever.get(FragmentActivity)
public RequestManager get(@NonNull FragmentActivity activity) {
//检查是否在子线程执行
if (Util.isOnBackgroundThread()) {
//暂时忽略子线程启动的流程
return get(activity.getApplicationContext());
}
//检查activity是否销毁了
assertNotDestroyed(activity);
//拿到v4包的Fragment管理器
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, null, isActivityVisible(activity));
}
这里暂时先忽略子线程启动的流程,以后再来给大家介绍。
这里可以看到 Glide
会检查当前传入的 activity
的状态:
/**
* Android 4.2以上执行,判断当前Activity是否销毁了(activity.isDestroyed()是4.2以上才有的api)
*
* @param activity 当前activity
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static void assertNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
}
}
可以看到这个判断方法只在 Android 4.2 上面执行,一旦发现传递进来的 activity
已经销毁了,那么就会抛出异常了,在使用 Glide
时必须注意到这一点。
Step7 RequestManagerRetriever.supportFragmentGet()
/**
* 获取一个感知外层生命周期的Fragment和网络请求管理类RequestManager
* 并让Fragment持有RequestManager
*
* @param context 当前传入的上下文
* @param fm Fragment管理器
* @param parentHint 可以传null,外层传入的Fragment
* @param isParentVisible 是否显示
* @return RequestManager {@link exercise.fritz.com.glide.RequestManager}
*/
@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 = current.getRequestManager();
//如果是空,则生成一个新的
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = mRwFactory.build(glide,
current.getGlideLifecycle(),
current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
关于 Glide
感知外层生命周期的原理具体可以看我的这篇 blog 。上面的代码我都写上了中文注释,不过 getSupportRequestManagerFragment
与其相关的方法参数,还是需要看一下的:
/**
* handler发消息的标记,通知清空pendingSupportRequestManagerFragments Map里面的数据
*/
private static final int ID_REMOVE_SUPPORT_FRAGMENT_MANAGER = 2;
/**
* 存储外层感知生命周期的v4包的Fragment集合
*/
final Map<FragmentManager, SupportRequestManagerFragment>
pendingSupportRequestManagerFragments = new HashMap<>();
/**
* 获取当前Activity上面的感知生命周期的SupportRequestManagerFragment
* 如果没有,就生成一个新的
*
* @param fm Fragment管理器
* @param parentHint 可以是null,外层传入的Fragment
* @param isParentVisible 是否显示
* @return 感知外层生命周期的Fragment
*/
public SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
//寻找当前显示的Glide用来感知外层生命周期的Fragment
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//如果为null,生成一个新的感知外层生命周期的Fragment
if (current == null) {
//使用map的key确保一个FragmentManager同一时间只生成一个感知生命周期的Fragment
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
//如果外层是显示状态
if (isParentVisible) {
//启动生命周期监听的回调
current.getGlideLifecycle().onStart();
}
//存储当前的感知外层生命周期的fragment
pendingSupportRequestManagerFragments.put(fm, current);
//提交运行fragment
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//发送消息,清空刚存进去的Fragment
mHandler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
这里生成或获取一个可以感知外层生命周期的 Fragment
,值得一提就是这里使用了一个 map
来确保一个 FragmentManager
同一时间只生成一个感知生命周期的 Fragment
,一旦 Fragment
顺利生成后再又把它在 map
里面清空:
@Override
public boolean handleMessage(Message msg) {
boolean handled = true;
Object removed = null;
Object key = null;
switch (msg.what) {
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) msg.obj;
key = supportFm;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
default:
handled = false;
break;
}
if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
}
return handled;
}
### Step8 RequestManagerRetriever.RequestManagerFactory.build()
在上面的 supportFragmentGet
方法里面,我们看到了一个 mRwFactory
对象,它生成了一个全新的 RequestManager
,它其实就是 RequestManagerRetriever
的一个内部类:
/**
* 用于创建RequestManager的工厂接口
*/
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
而且在 RequestManagerRetriever
里面已经有一个简单的静态单例的默认实现了:
/**
* 用于创建RequestManager的工厂接口实现对象
*/
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);
}
};
mRwFactory
就是在构造方法里面给赋值的:
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
mHandler = new Handler(Looper.getMainLooper(), this);
mRwFactory = factory != null ? factory : DEFAULT_FACTORY;
}
到此,Glide
的 with(FragmentActivity)
的流程就全部解析完成了,不过还是从中学到了一些东西,其中包括:
- 通过清单文件反射加载外层文件的方法
private static
的代码规范- 通过
Fragment
来感知外层生命周期的方法
我这里介绍的流程就只是 Glide
众多使用流程里面的比较简单的一个,不过看懂一个主流程后,再看其他的流程,心里就有底了。
下次见面给大家介绍一下 load(URL)
里面流程了,这些都是 RequestManager
里面的一些处理了,还请期待。