目录
一,介绍
Glide目前是安卓最主流的加载图片的框架,也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源码,可能需要半年甚至更多的时间。
但是如果分析过Glide的源码,不仅对我们的架构能力有很大提高,也会对面试中的关于Glide的问题知其然更知其所以然。
Glide的精髓,在于它的生命周期的管理和缓存策略。
二,使用
Glide的使用及其简单
java
// 项目的build.gradle添加依赖
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
在清单文件添加网络权限:
java
<uses-permission android:name="android.permission.INTERNET"/>
布局文件很简单就一个imageview:
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
使用:
Kotlin
class MainActivity : AppCompatActivity() {
//图片url
private val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val iv =findViewById<ImageView>(R.id.iv)
Glide.with(this).load(url).into(iv)
}
}
效果:
三,源码分析思路
Glide的源码分析,我们可以从使用角度,拆分为三部分去分析。
java
class MainActivity : AppCompatActivity() {
//图片url
private val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val iv =findViewById<ImageView>(R.id.iv)
//第一步 调用with 得到RequestManager
val requestManager:RequestManager = Glide.with(this)
//第二步 RequestManager调用load 得到requestBulider
val requestBulider:RequestBuilder<Drawable> =requestManager.load(url)
//第三步 requestBulider调用into
requestBulider.into(iv)
}
}
这样拆分的话,思路会比较清晰。
四,with源码分析
首先我们看一下with的源码:
java
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getContext()).get(fragment);
}
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
它可以接受的参数类型很多,确保多种场景下的使用
然后继续往下看getRetriever这个函数:
java
@NonNull
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();
}
判空不用看,直接看get(context)这个函数:
java
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
这个就是我们熟悉的双重检测单例模式,不了解的可以参考文章:Android 设计模式--单例模式_android开发饿汉单例-CSDN博客
然后我们看看 checkAndInitializeGlide(context, annotationGeneratedModule):
java
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
// 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, generatedAppGlideModule);
isInitializing = false;
}
这里好像没有什么具体的信息,我们接着往下看initializeGlide(context,generatedAppGlideModule)这个函数:
java
@GuardedBy("Glide.class")
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
好的,依然继续往下看initializeGlide(context, new GlideBuilder(), generatedAppGlideModule)
java
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
//获取应用级别的上下文
Context applicationContext = context.getApplicationContext();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
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());
}
}
//通过注解生成的代码拿到 RequestManagerFactory
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
//将拿到的工厂添加到 GlideBuilder
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//通过 Builder 建造者模式,构建出 Glide 实例对象
Glide glide = builder.build(applicationContext);
//注册组件回调
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
module.registerComponents(applicationContext, glide, glide.registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: "
+ module.getClass().getName(),
e);
}
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
//将构建出来的 glide 赋值给 Glide 的静态变量
Glide.glide = glide;
}
这个函数里面的信息量是非常大的,主要是进行了一系列的初始化操作,通过 Builder 建造者模式,构建出 Glide 实例对象,接着我们看看builder模式进行了哪些构建:
java
@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);
}
//RequestManagerRetriever 请求管理类
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
这里就完成了Glide的构建。
然后我们回到最开始的getRetriever(activity).get(activity),看看这个函数里面都干了些什么:
java
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
//首先判断当前是否在子线程中
if (Util.isOnBackgroundThread()) {
//在子线程中 就通过Application级别的上下文加载
return get(activity.getApplicationContext());
} else {
//检查Activity是否已经销毁
assertNotDestroyed(activity);
//拿到当前activity的fragmentmanager
FragmentManager fm = activity.getSupportFragmentManager();
//生成一个fragment 然后绑定一个请求管理类RequestManager
return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
看到这里,我们就应该意识到一个问题,如果我们在子线程中去调用Glide的话,就会使用应用级别的上下文去加载图片,这样大量使用,可能会导致内存泄漏。
然后在主线程中使用,就是Glide的精髓之一了,加载一个透明fragment来感应当前页面的生命周期的变化。
接着看看supportFragmentGet是怎么实现的:
java
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
//在当前的 Acitivty 添加一个 Fragment 用于管理请求的生命周期
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
//拿到当前请求的管理类
RequestManager requestManager = current.getRequestManager();
//如果为空 就创建一个
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
这里就是添加一个fragment管理生命周期。然后返回一个RequestManager对象。
接下来再具体看看getSupportRequestManagerFragment是怎么添加的:
java
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
//通过tag拿到fragment实例 避免重复
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);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
这里主要是拿到fragment实例。
从上面我们可以看出Glide主要是做了一些初始化的工作,缓存,线程池,复用池的构建等等。
然后绑定了一个fragment来管理生命周期
with的源码差不多就是这些,可能比较繁琐,但是不像rxjava那样绕来绕去的,主线还是比较清晰的。
五,模拟Glide生命周期管理
首先创建一个接口,监听生命周期回调:
java
public interface LifecycleListener {
void onCreate();
void onStart();
void onStop();
void onDestroy();
}
然后创建一个用来管理生命周期监听的接口:
java
public interface Lifecycle {
void addListener(@NonNull LifecycleListener listener);
void removeListener(@NonNull LifecycleListener listener);
}
通过上面的分析,我们知道Glide传入的上下文有应用级别的和非应用级别的。所以我们首先创建一个应用级别的Lifecycle:
java
public class ApplicationLifecycle implements Lifecycle {
@Override
public void addListener(@NonNull LifecycleListener listener) {
/**
* APP启动的时候,执行onCreate
*/
listener.onCreate();
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
//APP销毁的时候,啥也不用做了
}
}
然后创建一个非应用级别的lifecycle:
java
public 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.onCreate();
} else {
listener.onStop();
}
}
@Override
public void removeListener(@NonNull LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onCreate();
}
}
void onStop() {
isStarted = false;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onStop();
}
}
void onDestroy() {
isDestroyed = true;
for (LifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onDestroy();
}
}
}
创建一个具体的RequestManager 管理生命周期:
java
public class RequestManager implements LifecycleListener {
private Lifecycle lifecycle;
public RequestManager(Lifecycle lifecycle, Context applicationContext) {
this.lifecycle = lifecycle;
this.lifecycle.addListener(this);
}
@Override
public void onCreate() {
Log.d(LOG.TAG, "yh-----onCreate");
}
@Override
public void onStart() {
Log.d(LOG.TAG, "yh-----onStart");
}
@Override
public void onStop() {
Log.d(LOG.TAG, "yh-----onStop");
}
@Override
public void onDestroy() {
Log.d(LOG.TAG, "yh-----onDestroy");
this.lifecycle.removeListener(this);
}
}
创建一个空白的fragment:
java
public class RequestManagerFragment extends Fragment {
private final ActivityFragmentLifecycle lifecycle;
@Nullable
private RequestManager requestManager;
public RequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
@VisibleForTesting
@SuppressLint("ValidFragment")
public RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
@NonNull
public ActivityFragmentLifecycle getGlideLifecycle() {
return lifecycle;
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.lifecycle.addListener(requestManager);
}
@Nullable
public RequestManager getRequestManager() {
return requestManager;
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
}
简单写一个Glide管理类:
java
public class Glide {
private static volatile Glide glide;
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
glide = new Glide();
}
}
}
return glide;
}
@NonNull
public static RequestManager with(@NonNull Context context) {
return new RequestManager(new ActivityFragmentLifecycle(),context);
}
@NonNull
public static RequestManager withApplication(@NonNull Context context) {
return new RequestManager(new ApplicationLifecycle(),context);
}
}
使用也很简单:
java
public class DemoActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Glide.with(this);
Glide.withApplication(this.getApplicationContext());
}
}
这样当DemoActivity创建时,会创建一个ActivityFragmentLifecycle,执行它的onStart方法,从而调用RequestManager的onStart方法,onDestory也是同样的道理。这样就实现了生命周期的检测。这里只是简单写下有助于理解Glide内部是怎么做的。
关于load和into以及缓存机制 改天再写。