glide性能优化实战
前言
项目利用glide加载图片之前也只是会基本api,这次项目有非常多的图片需要展示,而且设备是一个android12的版本,但是性能不太理想,分给APP的资源不太多,以是需要优化现有图片加载逻辑,读者可以根据自己的项目自行选择优化项。
关于Glide的简单先容
Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及主动的资源池技术。
Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是云云的机动,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide利用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide 的主要目的是让任何情势的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide险些能满意你对远程图片的拉取/缩放/体现的一切需求。
API
Glide 利用简明的流式语法API,这是一个非常棒的计划,因为它允许你在大部门情况下一行代码搞定需求:
- Glide.with(context)
- .load(url)
- .into(imageView);
复制代码 性能
Glide 充分考虑了Android图片加载性能的两个关键方面:
- 图片解码速度
- 解码图片带来的资源压力
为了让用户拥有良好的App利用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪耀和抖动征象。
Glide利用了多个步调来确保在Android上加载图片尽可能的快速宁静滑:
- 主动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
- 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
- 深度的生命周期集成,以确保仅优先处理活泼的Fragment和Activity的请求,并有利于应用在须要时开释资源以避免在后台时被杀掉。
关于Glide的初步优化
上面都是官网的先容,下面我们进行初步的一个优化。
缓存计谋
起首是图片的缓存计谋。几个可配置的缓存计谋属性在DiskCacheStrategy类中都有先容
- NONE 不利用缓存,每次都重新加载
- DATA 在解码之前,将检索到的数据直接写入磁盘缓存。
- RESOURCE 在解码后,再将检索到的数据写入磁盘缓存。
- AUTOMATIC 实验根据DataFetcher和EncodeStrategy中的ResourceEncoder(假如ResourceEncoder可用的话)的数据源智能地选择计谋。
- ALL 假如是远程数据利用DATA和RESOURCE缓存,假如是当地数据利用RESOURCE缓冲。
项目加载的都是当地图片,以是在加载速度和缓存巨细的权衡下,利用了RESOURCE
- ...
- .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
- ...
复制代码 图片裁剪
因为缓存巨细跟图片巨细是有直接关系的,以是加载前最好将其裁剪为和控件巨细一致,避免过大的图片造成ANR和Out Of Memory
- ...
- .override(your size)
- ...
复制代码 移除加载动画
Glide为了保证图片加载的过分流通性,不显得突兀,是有默认的动画和变换的,但这也会斲丧一定的性能,以是我们将它关闭
- ...
- .dontAnimate()
- .dontTransform()
- ...
复制代码 其他
(可选)假如需要在加载过程中对图片进行处理,可以利用RequestListener
初步效果
都加上过后大概是这个样子
- Glide.with(context)
- .load(url)
- .override(your size)
- .dontAnimate()
- .dontTransform()
- .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
- .into(imageView);
复制代码 可以从Profiler中看到加载一个list的图片时,内存和CPU都有降落。
关于Glide的AppGlideModule定制
在新版Glide中,可以通过自界说AppGlideModule来全局界说glide的设置
- import android.content.Context
- import com.bumptech.glide.Glide
- import com.bumptech.glide.GlideBuilder
- import com.bumptech.glide.Registry
- import com.bumptech.glide.annotation.GlideModule
- import com.bumptech.glide.load.DecodeFormat
- import com.bumptech.glide.load.engine.bitmap_recycle.LruArrayPool
- import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool
- import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper
- import com.bumptech.glide.load.engine.cache.LruResourceCache
- import com.bumptech.glide.load.engine.cache.MemorySizeCalculator
- import com.bumptech.glide.load.engine.executor.GlideExecutor
- import com.bumptech.glide.module.AppGlideModule
- import com.bumptech.glide.request.RequestOptions
- import com.fawvw.hmi.media.common.utils.LogUtil
- import java.io.File
- @GlideModule
- class MyAppGlideModule : AppGlideModule() {
- private val TAG = "MyAppGlideModule"
- //图片文件缓存 10M
- private var IMAGE_CACHE_COUNT = 10 * 1024 * 1024
- private val SOURCE_EXECUTOR_NAME = "source"
- private val ANIMATION_EXECUTOR_NAME = "animation"
- override fun applyOptions(context: Context, builder: GlideBuilder) {
- super.applyOptions(context, builder)
- val calculator = MemorySizeCalculator.Builder(context).build()
- val defaultMemoryCacheSize = calculator.memoryCacheSize
- val defaultBitmapPoolSize = calculator.bitmapPoolSize
- val defaultArrayPoolSize = calculator.arrayPoolSizeInBytes
- LogUtil.d(
- TAG,
- "defaultMemoryCacheSize: $defaultMemoryCacheSize, defaultBitmapPoolSize: $defaultBitmapPoolSize, defaultArrayPoolSize: $defaultArrayPoolSize"
- )
- builder.setDefaultRequestOptions(
- RequestOptions().format(DecodeFormat.PREFER_RGB_565)
- )
- val cacheLocation = File(context.externalCacheDir, "GlideCache")
- if (!cacheLocation.exists()) {
- cacheLocation.mkdirs()
- }
- //设置glide文件缓存为10M
- builder.setDiskCache {
- DiskLruCacheWrapper.create(cacheLocation, IMAGE_CACHE_COUNT.toLong())
- }
- //设置glide内存,bitmap池,数组池砍
- builder.setMemoryCache(LruResourceCache((defaultMemoryCacheSize / 4).toLong()))
- builder.setBitmapPool(LruBitmapPool((defaultBitmapPoolSize / 4).toLong()))
- builder.setArrayPool(LruArrayPool(defaultArrayPoolSize / 4))
- //设置Source线程最大数量为1
- builder.setSourceExecutor(
- GlideExecutor.newSourceBuilder()
- .setThreadCount(1)
- .setName(SOURCE_EXECUTOR_NAME)
- .build()
- )
- //设置Animation线程最大数量为1
- builder.setAnimationExecutor(
- GlideExecutor.newAnimationBuilder()
- .setThreadCount(1)
- .setName(ANIMATION_EXECUTOR_NAME)
- .build()
- )
- }
- override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
- super.registerComponents(context, glide, registry)
- }
- }
复制代码 编译过后,就可以调用GlideApp了,用于将Glide替换掉,注意别忘了添加@GlideModule注解。
总结
在进行了上面的两个定制过后,CPU和内存都有显着的降落,但是有些配置确实会导致加载速度变慢和用户体验变差,需要自己权衡。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |