声明: 我目前分析的源码是最新的Glide源码:4.12.0版本
1 2 implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
1. Glide简介 Glide是一个支持拉取,解码和展示视频快照,图片,和GIF动画的框架,正如它的名字翻译一样:滑翔。让用户加载任何形式的图片列表尽可能地变得更快、更平滑。
Glide 使用简明灵活的流式语法API,允许你在大部分情况下一行代码搞定需求:
1 2 3 Glide.with(fragment) .load(url) .into(imageView);
默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection
的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
2. 性能 Glide 充分考虑了Android图片加载性能的两个关键方面:
为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:
自动、智能地下采样(downsampling
)和缓存(caching
),以最小化存储开销和解码次数;
积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。
3. 源码分析 关于Glide的详细使用介绍 ,参见前面链接即可,但是分析源码也要有个开始吧,那我们就从最基本的用法入手,Glide最基本的用法就是三段论:with、load和into。那我们现在就先从with开始。
3.1 生命周期的作用域(1.Application, 2.Activity, 3.Fragment) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static RequestManager with (@NonNull Context context) { return getRetriever(context).get(context); } public static RequestManager with (@NonNull Activity activity) { return getRetriever(activity).get(activity); } public static RequestManager with (@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); } public static RequestManager with (@NonNull Fragment fragment) { return getRetriever(fragment.getContext()).get(fragment); } public static RequestManager with (@NonNull View view) { return getRetriever(view.getContext()).get(view); }
从Glide.with()静态方法中,我们可以看到方法可以传入5个参数:Context、Activity、FragmentActivity、Fragment或者View。按照作用域分,我们可以把它分成两类:Application类和非Application类。
Application类:它的生命周期是全局的,没有空白Fragment就绑定Activity/Fragment。
非Application类,它的生命周期跟随Activity和Fragment的生命周期,专门有一个空白Fragment绑定Activity/Fragment。
从上面with的重载方法看出都会调用到getRetriever()方法,他其实最终就是返回RequestManagerRetriever对象,紧接着,我们看看RequestManagerRetriever的get方法。这里先分两个来看:
Activity、FragmentActivity、Fragment和View
Context
3.1.1 Activity类的get() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public RequestManager get (@NonNull Activity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else if (activity instanceof FragmentActivity) { return get((FragmentActivity) activity); } else { assertNotDestroyed(activity); frameWaiter.registerSelf(activity); android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm, null , isActivityVisible(activity)); } } private RequestManager fragmentGet ( @NonNull Context context, @NonNull android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) { RequestManagerFragment current = getRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null ) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); if (isParentVisible) { requestManager.onStart(); } current.setRequestManager(requestManager); } return requestManager; }
3.1.2 Context类的get() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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); } private RequestManager getApplicationManager (@NonNull Context context) { if (applicationManager == null ) { synchronized (this ) { if (applicationManager == null ) { Glide glide = Glide.get(context.getApplicationContext()); applicationManager = factory.build( glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context.getApplicationContext()); } } } return applicationManager; }
3.1.3 小结 Glide的with()生命周期总结如下图
子线程中Glide调用get()、传入ApplicationContext和ServiceContext,对应的生命周期属于Application域,生命周期和Application一致
Activity、Fragment和View对应的生命周期是被代理Fragemnt监控的,Glide内部逻辑会根据Activity的生命周期做相应调整
3.2 Glide生命周期感知过程 如3.1.1小节中分析的,不管with传入的是fragment、Activity还是View,RequestManagerRetriever都会创建一个没有UI的Fragment(SupportRequestManagerFragment)来当代理,当用户自定义的Activity或者Fragment生命周期发生变化的时候,Glide内部可以通过代理Fragment知道生命周期发生的变化,因此内部也做相应的处理。例如下载并且加载是一个比较耗时操作,如果下载完成之后,Activity已经被销毁了,那就不用加载了,所有这就是Glide感知组件生命周期的意义,用户不用主动调用clear()方法来释放资源了。关联关系如下图。
3.3 Glide与空Fragment绑定过程 从3.1.3小结中可以知道,只有在主线程 中调用with()并且传入Activity或者Fragment会绑定空Fragment。当传入的activity,这个activity上覆盖的空Fragment是RequestManagerFragment;当传入的是fragment,覆盖在上面的空fragment是SupportRequestManagerFragment。逻辑都是一样的,下面以传入fragment来分析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments = new HashMap<>(); private RequestManager supportFragmentGet ( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null ) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); if (isParentVisible) { requestManager.onStart(); } current.setRequestManager(requestManager); } return requestManager; } private SupportRequestManagerFragment getSupportRequestManagerFragment ( @NonNull final FragmentManager fm, @Nullable Fragment parentHint) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null ) { current = pendingSupportRequestManagerFragments.get(fm); if (current == null ) { current = new SupportRequestManagerFragment(); current.setParentFragmentHint(parentHint); pendingSupportRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
从supportFragmentGet()方法中我们看到了Glide内部逻辑和空Fragment的绑定过程。
不知道大家有没有疑惑:为什么在getSupportRequestManagerFragment()方法中要在pendingSupportRequestManagerFragments中临时保存空Fragment?
其实就是为了避免 SupportRequestManagerFragment 在一个作用域中重复创建。 因为commitAllowingStateLoss() 是将事务 post 到消息队列中的,也就是说,事务是异步处理的,而不是同步处理的。假设没有临时保存记录,一旦在事务异步等待执行时调用了Glide.with(…) ,就会在该作用域中重复创建 Fragment。
3.4 生命周期的详细监听过程 从上面小节分析可以看出,生命周期的管理,主要对Activity、Fragment和View(实质也是Activity或Fragment)有效,其他的都是Application域,没必须分析。所以后面的分析都是基于Activity或者Fragment的生命周期,而这两个逻辑都是一样的,我们还是以Fragment的分析为例。
从前面看出,每个Activity或者Fragment域都会创建一个空Fragment盖在上面。下来我们就从这个空Fragment开始分析Glide的生命周期是如何受影响的。Fragment盖的空Fragment是SupportRequestManagerFragment.java,那我们就从这里开始。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class SupportRequestManagerFragment extends Fragment { private final ActivityFragmentLifecycle lifecycle; public SupportRequestManagerFragment () { this (new ActivityFragmentLifecycle()); } @VisibleForTesting @SuppressLint("ValidFragment") public SupportRequestManagerFragment (@NonNull ActivityFragmentLifecycle lifecycle) { this .lifecycle = lifecycle; } @Override public void onStart () { super .onStart(); lifecycle.onStart(); } @Override public void onStop () { super .onStop(); lifecycle.onStop(); } ActivityFragmentLifecycle getGlideLifecycle () { return lifecycle; } ...... }
从3.1.1小节可以看到,创建RequestManager时是通过工厂创建的,那我们在看看这个工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Glide glide = Glide.get(context); requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); public interface RequestManagerFactory { @NonNull RequestManager build ( @NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) ; } 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); } };
RequestManager工厂在创建RequestManager的时候,传入了glide和lifecycle,在RequestManager中完成绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class RequestManager implements ComponentCallbacks2 , LifecycleListener ,... { RequestManager( Glide glide, Lifecycle lifecycle, RequestManagerTreeNode treeNode, RequestTracker requestTracker, ConnectivityMonitorFactory factory, Context context) { this .glide = glide; this .lifecycle = lifecycle; this .treeNode = treeNode; this .requestTracker = requestTracker; this .context = context; ...... if (Util.isOnBackgroundThread()) { Util.postOnUiThread(addSelfToLifecycle); } else { lifecycle.addListener(this ); } ...... } public synchronized void onStart () { resumeRequests(); targetTracker.onStart(); } public synchronized void onStop () { pauseRequests(); targetTracker.onStop(); } }
至此,生命周期的详细监听过程就通了。
总结: 调用with()创建RequestManager,创建RequestManager传入Lifecycle对象(这个对象是在无界面 Fragment 中创建的),RequestManager通过Lifecycle通知Glide内部的各个业务Traker。
当 Fragment 的生命周期变化时,无界面 Fragment会感知到生命周期变化,然后通过Lifecycle 对象将事件分发到 RequestManager,RequestManager的onStart()将事件分发给targetTracker,targetTracker分发给Glide内部逻辑。
参考文档:
1.Glide简介
2.郭霖关于Glide的源码分析