前言:OKHttp和Retrofit都摸完了,今天咱们换换口味,顺藤摸一下Glide源码。Glide一听都是说源码太难看了,不是人看的。那咱们今天就解开它的神秘面纱,看看是不是人看的?O(∩_∩)O哈哈~
一、Glide浅谈
Glide相信大家都用过,因为太好用了。一句话总结就是:一行代码搞定,妈妈再也不用担心我的图片加载问题了。 \(^o^)/~
1. 当然了,每个框架必然有优点和缺点:
优点:
- 多样化媒体加载
- 生命周期集成
- 高效的缓存策略
- 内存开销小
缺点:
- 虽然,Glide貌似一行代码可以搞定,但是真正要把它用活还是比较复杂的。
- Glide功能强大,所以使用的方法非常多,源码也相对复杂,包较大
2. 我们撸源码的目的:
- 经常面试会问到,这是NO.1
- Glide是非常优秀的框架,我们可以学习它的设计思想
- 可以学习它使用无UIFragment来响应生命周期回调,这和Jetpack的思想是一致的。
- 框架源码看多了,很多架构的骨架会在你脑海里形成体系,当你自己去实现一个框架的时候,可以套用。
3. 我们要弄懂Glide的什么知识
4. 我们怎么撸Glide源码
Glide.with(this)
.load("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=false")
.into(imageView)
根据最简单的一句代码解决问题,我们有三条主线(只需要跟踪主线就够了,太深入反而把自己绕晕):
- Glide的with主线
- Glide的load主线
- Glide的into主线
二、Glide的with主线
根据上边的代码,使用Glide去加载图片,首先的使用:Glide.with()。我们来摸摸这条主线:
2.1 先说说这条主线的几个关键类:
- GlideBuilder: Glide的建造者类,复杂构建一个Glide实例,并添加各类默认线程池等。
- RequestManagerRetriever:它负责创建或从缓存中获取无UI的Fragment,与Activity绑定,实现生命周期方法监听。
- RequestManager:用来管理和start Glide请求的类。它根据绑定额生命周期的回调事件,自动的暂停、开始或者重启请求。
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
- SupportRequestManagerFragment:继承至androidx.app.fragment.Fragment适配androidX的Fragment,它是一个无UI的Fragment,它与Activity进行绑定,实现生命周期的监听,并通知lifecycle,lifecycle在通知它的lifecycleListeners。
- RequestManagerFragment:继承至android.app.Fragment,它是一个无UI的Fragment,它与Activity进行绑定,实现生命周期的监听,并通知lifecycle,lifecycle在通知它的lifecycleListeners。
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
- ActivityFragmentLifecycle:它就是5/6中的默认lifecycle,实现生命周期方法的回调分发。
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
2.2 跟踪with主线
- 它总的来说是通过getRetriever(activity)获取了一个RequestManagerRetriever对象,然后通过它的get方法返回一个RequestManager对象
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
- 跟踪 getRetriever(activity)方法发现,它是通过Glide实例的getRequestManagerRetriever()方法获取。
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
- Glide.get(context)就是获取Glide实例了,它是单例模式,只会有一个Glide实例。
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
1. 一路跟踪下去,最终会来到
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
...
2. 通过建造者模式创建Glide实例
Glide glide = builder.build(applicationContext);
...
Glide.glide = glide;
}
3. 在GlideBuild.java的build方法中创建出Glide实例,并为其添加各种默认的线程池、
内存计算器、网络监听工厂、Bitmap缓存池、还有RequestListener默认回调、引擎Engine...
Glide build(@NonNull Context context) {
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
...
if (engine == null) {
engine =
new Engine(
memoryCache,
...r,
isActiveResourceRetentionAllowed);
}
4. 这时候RequestManagerRetriever实例就构建出来了
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
...,
isImageDecoderEnabledForBitmaps);
}
- 这里在回到1.中的getRetriever(context).get(context);getRetriever(context)是返回一个RequestManagerRetriever对象,然后调用它的get()方法,这里我们进入到RequestManagerRetriever.get()方法中瞧瞧。
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
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
- 这里根据传过来的Context类型进入到 不同的方法中,在分支get()方法中,它将创建或者获取缓存的无UI的Fragment与Actvitiy进行关联,实现生命周期的监听;到最后实际上归于两种Fragment类型:一种是androidx.fragment.app.fragment;一种是android.app.fragment;也就是为了适配不同版本。
- 我们这里就看一种get((Activity) context),其他都类似。
6.1 fragmentGet()方法会从获取的RequestManagerFragment 获取RequestManager对象。
6.2 如果RequestManager 对象为空的话,将通过factory.build创建。
6.3 factory默认为DEFAULT_FACTORY ,它新建了一个RequestManager对象。而传入的current.getGlideLifecycle(),则是ActivityFragmentLifecycle对象,他负责生命周期方法的分发。
6.4 将ActivityFragmentLifecycle传入RequestManager后,RequestManager本身就实现了LifecycleListener,它自己就是一个监听者。所以链条为Fragment.onStart() > ActivityFragmentLifecycle.onStart() > RequestManager.onStart()
1. get((Activity) context)
public RequestManager get(@NonNull Activity activity) {
...
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
2.
private RequestManager fragmentGet( ...) {
RequestManagerFragment current = getRequestManagerFragment(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;
}
3.
private static final RequestManagerFactory DEFAULT_FACTORY =
new RequestManagerFactory() {
@Override
public RequestManager build(...) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
- 这里回到6中的这句获取RequestManagerFragment对象的这句代码。
7.1 先从FragmentManager中通过tag获取。
7.2 没有话就在pendingRequestManagerFragments里获取:pendingRequestManagerFragments是一个HashMap,它保存RequestManagerFragment;而pendingSupportRequestManagerFragments保存SupportRequestManagerFragment。
7.3 前两步还没有找到的话,就新建一个。通过new RequestManagerFragment()方法创建,但是它默认会通过this(new ActivityFragmentLifecycle()); 将ActivityFragmentLifecycle作为默认lifeCycle传进去。
7.4 如果Activity可见的会调用lifeCycle.onStart()方法,并分发给lifeCycle的监听器。
7.5 将RequestManagerFragment缓存到Map中。
7.6 将RequestManagerFragment与Activity绑定起来。
7.7 然后通过Handler发送一个通知,将前一个不属于Activity的RequestManagerFragment移除。
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
private RequestManagerFragment getRequestManagerFragment(...) {
7.1. 先从FragmentManager中通过tag获取
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
7.2. 没有话就在pendingRequestManagerFragments里获取pendingRequestManagerFragments
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
7.3. 前两步还没有找到的话,就新建一个
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
7.4. 如果Activity可见的会调用lifeCycle.onStart()方法,并分发给lifeCycle的监听器。
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
7.5. 将RequestManagerFragment缓存到Map中
pendingRequestManagerFragments.put(fm, current);
7.6. 将RequestManagerFragment与Activity绑定起来
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
7.7 然后通过Handler发送一个通知,将前一个不属于Activity的RequestManagerFragment移除
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
- 跟踪到这,with主线我们也清晰了。在这条主线里主要是:
首先:getRetriever()返回了一个RequestManagerRetriever对象,在这个过程中构建了Glide的单例对象,清晰了Glide通过GlideBuilder建造者模式创建,并初始化了很多线程池,缓存池等。
然后:通过RequestManagerRetriever.get()方法返回一个RequestManager对象,在这个过程中Glide最重要的生命周期监听和绑定会呈现在我们面前,它通过构建一个无UI的Fragment与Activity进行绑定,那么当Activity有生命方法回调时,Fragment也会回调它的lifeCycle相对于的方法,在lifeCycle里就会将生命周期方法进行分发给他的监听器。而本身RequestManager实现了LifecycleListener接口,它就是一个生命周期的监听者。
- 跟踪到这,with主线我们也清晰了。在这条主线里主要是:
三、Glide的load主线
load主线其实就是进入到RequestManager里的load方法中去了,其实它还有很多重载方法,支持各种参数如Bitmap、Drawable、String、Uri和File等,这也是Glide多样化体现之一。
val requestBuilder: RequestBuilder<Drawable> = requestManager.load("")
- 前面with主线返回的是一个RequestManager实例,load主线就是通过RequestManagert.load()方法返回了一个RequestBuilder对象。
- 它的源码还是比较简单,asDrawable()实则新建了一个RequestBuilder对象。然后调用了RequestBuilder.load()方法将Uri传入并赋值给model。
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
四、Glide的into主线
这条主线才Glide的重中之重:在这条主线里包括了Glide的核心功能:切换子线程去请求数据、它的缓存处理机制以及获取图片的stream后,切换为主线程转为为对应的格式交由ImageView显示。
由于篇幅问题,这里又是重中之重,再加上我也是读者,发现文章太长其实挺恶心的,读起来费时费力。所以我们另起一文聊聊,
网友评论