再开始写文章之前非常感谢这篇博客的作者。是他的这篇文章给了我glide源码阅读的一些灵感。在这之前几次阅读都没有搞明白的glide加载流程在阅读了他的这篇文章后参考类似的方法对glide的源码结构有了一个比较清晰的认识。下面是他的这篇文章的地址:
https://blog.csdn.net/carson_ho/article/details/79212841
前言
glide是我们项目开发中非常常见的一个三方框架,它的功能极其强大它为我们出来好了图片的加载缓存等功能。使用起来非常方便。那么我们应该如何来进行使用呢?它的实现原来又是什么呢?
Glide地址: https://github.com/bumptech/glide
Glide官方使用文档: https://muyangmin.github.io/glide-docs-cn/doc/options.html
文章glide的使用版本:4.9.0
本篇文章主要对glide的加载流程进行分析。
基本使用
-
简单的加载
//context可以使activity,application,fragment //imageUrl为图片地址 //image 需要显示的图片 Glide.with(context).load(imageUrl).into(image);
-
设置占位图以及加载出错的图片
Glide.with(context) .load(imageUrl) .placeholder(R.drawable.coordinator_demo) .error(R.drawable.coordinator_demo) .into(image);
上面是我们为单个图片的加载设置配置,但是常见的的情况下我们许多图片的加载除了加载地址和需要显示的ImageView不同其他的都是相同的。难道我们要为每一个图片的加载都进行设置吗?答案是否定的,glide为我们提供了一个对象:RequestOptions方便我们共享不同模块的图片加载项。
val requestOptions = RequestOptions() requestOptions .placeholder(R.drawable.coordinator_demo) .error(R.drawable.coordinator_demo) Glide.with(context).load(imageUrl).apply(requestOptions).into(image);
RequestOptions对象的创建非常简单,可以直接new一个对象或者通过它的任意一个静态方法的调用返回RequestOptions对象。
Glide源码分析
通过给glide的使用我们发现Glide的图片加载主要使用了三个方法:
-
with()
-
load()
-
into()
with方法
可以看到抛开废弃的方法Glide有5个重载的with.它们的返回对象都是RequestManager对象的实例。
通过阅读源码我们发现最终返回的RequestManager对象是由RequestManagerRetriever的get方法返回的。get()有5个重载方法分别对应Glide的5个重载。我们来一个一个进行分析。
-
传递的Context是Application的context.最终调用的是getApplicationManager方法。其实现如下:
@NonNull private RequestManager getApplicationManager(@NonNull Context context) { // Either an application context or we're on a background thread. if (applicationManager == null) { synchronized (this) { if (applicationManager == null) { // Normally pause/resume is taken care of by the fragment we add to the fragment or // activity. However, in this case since the manager attached to the application will not // receive lifecycle events, we must force the manager to start resumed using // ApplicationLifecycle. // TODO(b/27524013): Factor out this Glide.get() call. Glide glide = Glide.get(context.getApplicationContext()); applicationManager = factory.build( glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context.getApplicationContext()); } } } return applicationManager; }
这里通过双重锁的单例来保证针对Application的Context只有一个RequestManager.
-
传入对象是FragmentActivity
@NonNull public RequestManager get(@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet( activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } }
可以看到上面的代码最终会调用到supportFragmentGet方法,这里才是真正返回RequestManager的位置。
@NonNull private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { 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; }
因为这篇文章知识粗略的了解Glide的加载我们先不去深入分析这个RequestManager是如何生成的。
-
传入对象是Fragment
@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()); } }
同样的这里也是调用的supportFragmentGet来获取RequestManager对象。
这里我们不需要太过关注细节只需要知道Glide会根据传入的不同的activity或者Fragment来创建对应的requestManager。并与其生命周期进行绑定
load
Glide的with方法返回的是RequestManager接着我们看看RequestManager的load方法。