本文正在参与「金石计划」
对于Android开发者来说,Glide是最常运用的库。这儿介绍了开发过程中,7个运用Glide的技巧。
不要运用wrap_content
不清楚你是否这样运用过,把 ImageView 的宽和高设置成 wrap_content
,并经过Glide来加载图片
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Glide.with(context)
.load(url)
.into(image)
为什么不主张把ImageView设置成 wrap_content
,咱们看一下Glide的文档是怎么说的(文档地址中文地址 最新英文地址):
文档上写得很明显,在某些状况下会运用屏幕的尺寸替代 wrap_content
,这或许导致原来的小图片变成大图,Glide transform 问题剖析这篇文章就介绍了这种问题。为了防止这种状况发生,咱们最好是不要运用 wrap_content
。当然如果你实在是需求运用 wrap_content
,你能够按照Glide的主张,运用Target.SIZE_ORIGINAL。
需求注意的是:运用Target.SIZE_ORIGINAL 在加载大图时或许造成oom,因而你需求确保加载的图片不会太大。
自定义内存缓存巨细
在某些状况下,咱们或许需求自定义Glide的内存缓存巨细和Bitmap池的巨细,比方图片显示占大头的app,就期望Glide的图片缓存大一些。Glide内部运用MemorySizeCalculator类来决定内存缓存和Bitmap池的巨细。
@GlideModule
class MyGlideModel: AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
super.applyOptions(context, builder)
//经过MemorySizeCalculator获取MemoryCache和BitmapPool的size巨细
val calculator = MemorySizeCalculator.Builder(context).build()
val defaultMemoryCacheSize = calculator.memoryCacheSize
val defaultBitmapPoolSize = calculator.bitmapPoolSize
//依据业务计算出需求的缓存巨细,这儿简化处理,都乘以1.5
val customMemoryCacheSize = (1.5 * defaultMemoryCacheSize).toLong()
val customBitmapPoolSize = (1.5 * defaultBitmapPoolSize).toLong()
//设置缓存
builder.setMemoryCache(LruResourceCache(customMemoryCacheSize))
builder.setBitmapPool(LruBitmapPool(customBitmapPoolSize))
}
}
memoryCache 和 BitmapPool 的差异:
- memoryCache:经过key-value才缓存数据,缓存之前用过的Bitmap
- BitmapPool:重用Bitmap目标的目标池,依据Bitmap的宽高来复用。复用的原理能够看Bitmap全解析
详细差异见What is difference between MemoryCacheSize and BitmapPoolSize in Glide
自定义磁盘缓存
Glide 运用 DiskLruCacheWrapper 作为默许的 磁盘缓存 。 DiskLruCacheWrapper 是一个运用 LRU 算法的固定巨细的磁盘缓存。默许磁盘巨细为 250 MB ,方位是在应用的 缓存文件夹 中的一个 特定目录 。咱们也能够自定义磁盘缓存,代码如下:
@GlideModule
class MyGlideModel: AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
super.applyOptions(context, builder)
val size: Long = 1024 * 1024 * 100 //100MB
builder.setDiskCache(InternalCacheDiskCacheFactory(context, cacheFolderName, size))
}
}
牢记在onLoadCleared释放图片资源
如上图Glide的官方文档所示,咱们在运用Target时,必须在从头绘制(通常是View)或改变其可见性之前,你必须确保在onResourceReady中收到的任何当前Drawable不再被运用。这是由于Glide内部缓存在内存不足或许自动收回Glide.get(context).clearMemory()时,会收回Bitmap,如果此时ImageView还运用被收回的Bitmap,就会发生 trying to use a recycled bitmap 的过错。
处理办法是不再运用在onResourceReady中获取的Bitmap,代码如下:
Glide.with(this)
.load(Url)
.into(object : CustomTarget<Bitmap>(width, height) {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?,
) {
mBitmap = resource
}
override fun onLoadCleared(placeholder:Drawable?){
mBitmap = null
}
})
优先加载指定图片
如上图所示,当一个页面有多个图片时,咱们期望某些图片优先被加载出来(这个界面里边是上面的一拳超人的封面),某些图片后加载,比方这个界面里的互动点评的用户头像列表。Glide提供了优先级来处理这个问题,它的优先级如下:
- Priority.LOW
- Priority.NORMAL
- Priority.HIGH
- Priority.IMMEDIATE
运用代码如下:
Glide
.with(context)
.load("url")
.priority(Priority.LOW)//底优先级的图片
.into(imageView);
Glide
.with(context)
.load("url")
.priority(Priority.HIGH)//高优先级的图片
.into(imageView);
注意:优先级高的加载任务会尽量首先启动,但是无法确保加载开端或完结的次序。
慎用Glide.with(View)
咱们知道,Glide依据with()里边的参数来决定load的生命周期。
- 当运用with(getActivity().getApplicationContext())时,即便当前activity或许Fragment被destory,它将继续load图片,然后图片被解码、缓存,乃至或许被设置到ImageView中,最后才被废物收回;
- 当运用with(Fragment)时,Glide会监听Fragment的生命周期,一旦Fragment被中止,任何未完结的恳求都会被暂停;而当销毁时,所有未完结的恳求都会被清除。
- 运用with(getActivity())时,Glide会监听Activity的生命周期,只有在Activity被中止或销毁的时分,才会暂停或许清除未完结的load恳求。
- 运用with(view)时,Glide将做与with(view.getContext())相同的事情,这相当于上面的Activity状况,而不是with(Fragment)。
加载大图时运用skipMemoryCache
当咱们运用Glide加载大图时,应该防止运用内存缓存,如果不好好处理或许发生oom。在Glide中,咱们能够运用skipMemoryCache来跳过内存缓存。代码如下:
Glide.with(context)
.load(url)
.skipMemoryCache(true)
.into(imageview)
与skipMemoryCache对应的是 onlyRetrieveFromCache,它只从缓存中获取目标,不会从网络或许本地缓存中就直接加载失利。
参阅
- Glide transform 问题剖析
- Glide官方文档