安卓Glide那些事情面试,一篇全部搞定
- 一.Glide有几级缓存???
- 二.Gllide源码分析
- 三.内存缓存和磁盘缓存LruCache算法
- 四.Gllide基本使用
- 五.Gllide高级使用:配置
- 1.配置内存和磁盘缓存大小
- 2.配置okhttp
- 3.配置https认证
- 4.使用
一.Glide有几级缓存???
Gllide的四级缓存流程图:
通过上面这个流程图,我们可以知道Glide的缓存可以分为四级,第一个是ActiveResources,第二个是MemoryCache内存缓存,第三个是DiskCache磁盘缓存,第四个是网络获取。ActiveResources使用弱引用,内存缓存和磁盘缓存使用LruCache近期最少使用原则
Gllide的源码分析流程:
我们主要讨论这三个缓存,不讨论网络缓存
范围:
1、活动缓存:在某个Activity范围,页面退出该缓存就不存在
2、内存缓存:某个App范围,应用完全退出就不存在
3、磁盘缓存:整个系统,只要不删除数据,就一直存在
作用:
1、活动缓存:分担内存缓存的负担,
2、内存缓存:加快数据读取
3、磁盘缓存:进行永久性保持
活动缓存的说明
1、活动缓存并不是我们熟悉的内存缓存,是Glide自己定义的一种缓存策略。
2、本质上就是HasMap,用了一次就缓存,以后需要就直接拿,不需要就清除这个缓存。
3、该策略的存在也是为了及时释放内存,不需要等等整个应用退出再释放内存,减轻应用内存负担。
4、活动缓存比内存缓存小,如果活动缓存满了,会自动写到内存缓存。
5、系统会对内存缓存进行自动管理,只要不是快速存放大内存文件,并且不一直占有内存对象,都不会内存溢出。
内存缓存的说明
内存缓存是系统自身会管理的,但是可以继承LruCache,做进一步管理
磁盘缓存的说明
1、磁盘缓存本质是本地文件缓存,但是通过普通的文件写入读取效率不高。
2、Glide中使用了DiskLruCache框架进行数据保存和读取。
3、效率高的主要原因是:磁盘缓存对图片文件进行了加密和压缩处理。
总结
1、优先从活动缓存获取
2、活动缓存没有就再内存缓存中寻找
3、内存缓存没有,就去磁盘缓存读取
4、磁盘缓存没有就去网络获取本地文件读取
二.Gllide源码分析
https://blog.csdn.net/nufuli123/article/details/123806389
三.内存缓存和磁盘缓存LruCache算法
内存缓存:LruCache算法中LinkedHashMap
磁盘缓存: journal日志清单文件
磁盘读写也是用的LRU算法。但是这个和内存的LRU算法有一点小区别。为什么呢?因为内存缓存是我们运行的时候,程序加载内存里面的资源,可以直接通过一个LinkedHashMap去实现。但是磁盘不同,我总不可能吧所有磁盘的资源读出来然后加载在内存里面吧,这样的话,肯定会引发oom了。那么Glide是怎么做磁盘的LRU的呢?
Glide 是使用一个日志清单文件来保存这种顺序,DiskLruCache 在 APP 第一次安装时会在缓存文件夹下创建一个 journal 日志文件来记录图片的添加、删除、读取等等操作,后面每次打开 APP 都会读取这个文件,把其中记录下来的缓存文件名读取到 LinkedHashMap 中,后面每次对图片的操作不仅是操作这个 LinkedHashMap 还要记录在 journal 文件中. journal 文件内容如下图:
data/data/应用包名/cache/。。。。。
journal文件:
四.Gllide基本使用
Glide.with(this).load(url).into(imageView);//默认是开启内存缓存和磁盘缓存的。
1.内存缓存:
Glide.with(this)
.load(url)
.skipMemoryCache(true)//关闭内存缓存
.into(imageView);
2.磁盘缓存:
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)//磁盘缓存
.into(imageView);
一个 diskCacheStrategy( ) 方法就可以调整他的硬盘缓存策略。其中可以传入的参数有四种
DiskCacheStrategy.ALL : //表示既缓存原始图片,也缓存转换过后的图片。
DiskCacheStrategy.NONE: //表示不缓存任何内容。
DiskCacheStrategy.RESOURCE: //表示只缓存原始图片。
DiskCacheStrategy.RESULT: //(已过期,新api4.11修改为后面两个)表示只缓存转换过后的图片(默认选项)。
DiskCacheStrategy.DATA: //表示只缓存转换过后的图片。
DiskCacheStrategy.AUTOMATIC //表示智能判断选择模式(默认选项)。
3.清理缓存:
Glide.get(GlideActivity.this).clearMemory();//清除内存缓存
new Thread(new Runnable() {
@Override
public void run() {
Glide.get(GlideActivity.this).clearDiskCache();//清除SD卡缓存
}
}).start();
五.Gllide高级使用:配置
依赖:
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
// Glide集成OkHttp时需要使用的库,库已经将需要适配Okhhtp的大部分代码封装,注意如果之前已经使用了okhttp依赖注释掉
implementation "com.github.bumptech.glide:okhttp3-integration:4.13.0"
implementation 'com.github.bumptech.glide:glide:4.13.0'
kapt 'com.github.bumptech.glide:compiler:4.13.0'//Glide注解处理器的依赖
权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1.配置内存和磁盘缓存大小
@GlideModule
class MyGlideModule: AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
var memorySizeCalculator = MemorySizeCalculator.Builder(context).build()
//设置内存缓存大小
builder.setMemoryCache(LruResourceCache(memorySizeCalculator.memoryCacheSize.toLong()))
//设置磁盘缓存目录和大小,默认目录:"image_manager_disk_cache" 默认大小:250 * 1024 * 1024
builder.setDiskCache(InternalCacheDiskCacheFactory(context,"image",500 * 1024 * 1024))
}
}
2.配置okhttp
glide默认使用HttpUrlConnection请求网络图片
@GlideModule
class OkHttpLibraryGlideModule: LibraryGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
var client = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build()
registry.replace(GlideUrl::class.java,InputStream::class.java,OkHttpUrlLoader.Factory(client))
}
}
3.配置https认证
使用上面的代码去加载一些网络上的https图片一般是没有问题的,没问题是因为网络上的https使用的证书一般是权威机构颁发的证书,而这些权威机构的根证书在手机出厂时就已经预装在手机里面了,所以我们加载https图片时会自动完成认证,但是突然有一天,我们公司的网络请求也改成了Https了,用的是自定义证书,并不是权威机构颁发的,所以这个时候加载公司的https的图片时就加载失败了,异常如下:
Glide: Load failed for https://192.168.1.250:8080/cat.jpg with size [1080x162]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
There was 1 cause:
javax.net.ssl.SSLHandshakeException(java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)
看到CertPathValidatorException(证书路径验证器异常)不用我多说应该也知道是什么原理导致的了。
@GlideModule
class OkHttpLibraryGlideModule: LibraryGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
var client = OkHttpClient.Builder()
.sslSocketFactory(sSLSocketFactory, trustManager)//https认证
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build()
registry.replace(GlideUrl::class.java,InputStream::class.java,OkHttpUrlLoader.Factory(client))
}
/** 获取一个SSLSocketFactory */
val sSLSocketFactory: SSLSocketFactory
get() = try {
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, arrayOf(trustManager), SecureRandom())
sslContext.socketFactory
} catch (e: Exception) {
throw RuntimeException(e)
}
/** 获取一个忽略证书的X509TrustManager */
val trustManager: X509TrustManager
get() = object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) { }
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) { }
override fun getAcceptedIssuers(): Array<X509Certificate> { return arrayOf() }
}
}
4.使用
最后还有一步,第2步创建的类中使用了注解,Glide会自动生成一个GlideApp的类,这个类就是使用了我们配置的OkHttp的,所以在下载图片时,我们要使用GlideApp来代替之前的Glide类,如下:
GlideApp.with(this)
.load("https://192.168.1.250:8080/cat.jpg")
.centerCrop()
.placeholder(R.mipmap.ic_launcher)
.into(imageView)