Glide分析一

101 阅读3分钟

前言

Glide 网络请求为Okhttp时需要添加OkHttp依赖,如果需要自定义的OkHttpClient,需要做类似代码中registerComponents()方法中操作。默认Glide会为我们创建一个默认的OkHttpClient。

实例创建

Glide#with方法,Glide#get获取一个Glide实例,通过double check方式创建单实例。通过反射的方式创建GeneratedAppGlideModuleImpl实例。构造函数的参数是ApplicationContext。

  1. 解析Manifest中的Glide实例(已经废弃),通过注解的方式实现自定义配置。
  2. 通过注解生成代码,过来Manifest中的Module
  3. 构建Glide中GlideBuilder通过applyOptions()传递给每一个manifest中的Moudle和注解生成的module,对Glide构建时自定义
  4. 通过GlideBuilder#build()完成Glide创建
  5. 通过ApplicationContext#registerComponentCallbacks()监听应用配置改变和低内存的状态监听,通知给glide实例。

Glide处理缓存对象

  1. SourceExecutor:通过CPU核心数计算线程数,最大4个线程
  2. DiskCacheExecutor:线程数为1
  3. AnimatorExecutor:线程数是SourceExecutor的一半
  4. MemorySizeCalculator:计算各种缓存内存的大小
  5. ConnectivityMonitorfactor:在有网络状态情况下监听权限的情况,监听网络状态
  6. BitmapPool:bitmap缓存,Android 8 及以上版本缓存大小是0;在Android 8 以下版本缓存大小是4倍屏幕大小图片所需要的内存。
  7. ArrayPool:存储int数组和byte数组的缓存,大小是4M;如果是低内存大小是2M
  8. MemoryCache:Resource对象的缓存,Glide中很多对象是Resource,缓存大小是2倍屏幕大小图片所需要的内存
  9. DiskCacheFactory:本地磁盘缓存处理
  10. Engine:请求引擎
  11. RequestManagerRetriever:查找对应的Context的Requestmanager

MemorySizeCalculator

计算各种内存大小:BitmapPool,ArrayPool,MemoryCache等

Android 8.0以上的设备,Bitmap配置使用的是Config.HARDWARE,占用的是显存,不占用内存,Bitmap数据也无法修改,所以不缓存。

LruBitmapPool 是BitmapPool实现,大小是4倍屏幕大小图片占用的内存

  1. 检查Bitmap的状态,不为空,没有被回收,可以被修改,内存占用大小,小于当前BitmapPool的最大缓存值。
  2. 通过strategy#put方法完成缓存,strategy实现类通过SizeConfigstrategy
  3. 更新当前缓存的Bitmap数量和占用的缓存大小
  4. 通过evict()方法,检查是否达到了最大缓存值,如果达到最大缓存值,清除旧的Bitmap

处理过程:

  1. 通过Bitmap大小和配置计算Key,Keypool最多缓存20个key,如果没有缓存就创建一个新的,key的Hashcode根据Bitmap配置和大小计算的
  2. 通过GroupLinkedMap缓存Bitmap,类似于Hashmap,HashMap会移除相同的Key的数据。GroupedLinkMap不会移除相同的Key的数据,把相同的Key的数据以列表的形式串联起来。HashMap的get方法不会移除数据,而GroupLinkedMap的get方法会移除数据
  3. 重新计算当前配置Bitmap的数量,存储在sortedSizes中,它是一个HashMap,Key是Bitmap.Config,value是一个Map<Integer,Integer>(key是Bitmap大小,Value是对应的数量)

GroupedLinkedMap,类似LinkedEntry,它是一个双向循环的链表,存储了Value列表,LinkedEntry的新旧是通过双向的环状链表来排序。

LruArrayPool

LruArrayPool和LruBitmapPool类似,用来缓存int数组和byte数组的缓存池。

  1. 通过getAdapterFromtype()查找对应数组的Adapter
  2. 计算数组内存占用大小
  3. 如果数组过大,跳过缓存,直接退出方法;否则,继续操作
  4. 通过数组长度和arrayClass计算key
  5. 通过GroupedLinkedMap#put方法来缓存
  6. 更新缓存的数量
  7. 更新缓存占用的大小
  8. 计算是否达到缓存上限,达到上限移除最久的缓存,直到没有超过上限为止

总结

Glide优秀在于内存缓存和磁盘缓存,特别是磁盘缓存。