glide性能优化实战

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"//图片文件缓存 10Mprivate var IMAGE_CACHE_COUNT = 10 * 1024 * 1024private 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.memoryCacheSizeval defaultBitmapPoolSize = calculator.bitmapPoolSizeval defaultArrayPoolSize = calculator.arrayPoolSizeInBytesLogUtil.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文件缓存为10Mbuilder.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线程最大数量为1builder.setSourceExecutor(GlideExecutor.newSourceBuilder().setThreadCount(1).setName(SOURCE_EXECUTOR_NAME).build())//设置Animation线程最大数量为1builder.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和内存都有明显的下降,但是有些配置确实会导致加载速度变慢和用户体验变差,需要自己权衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/469345.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超详细:三大范式和反范式设计详解

目录 1、三大范式 第一范式: 列不可再分 。 第二范式: 行可以唯一区分 第三范式:确保数据的完整性、减少数据冗余和避免更新异常。 反方式模式 实验数据:模拟两张百万量级的数据表 反范式优化实验对比 反范式存在的问题 &am…

Python 实现阿里滑块全攻略

阿里划块技术为开发者提供了高精度的视觉分割能力,而 Python 作为一种简洁高效的编程语言,可以轻松调用阿里划块接口,实现各种场景下的图像分割需求。 Python 调用阿里云分割抠图 - 商品分割接口的步骤如下:首先,开通…

尤雨溪都点赞的测试工具,你还不用?

尤雨溪都点赞的测试工具,你还不用? 想要一个跨浏览器兼容、无闪退的测试体验?Playwright来了!它不仅支持主流浏览器自动化,还能轻松跨平台,让你轻松构建可靠的端到端测试。本文带你了解Playwright的功能亮点…

「IDE」VS2022插件 Visual Assist X 番茄助手介绍说明

✨博客主页何曾参静谧的博客📌文章专栏「IDE」集成开发环境📚全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C++」C/C++程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制开发「Py」Py

qt QFrame详解

1、概述 QFrame是Qt框架中用于提供框架或边框的控件,主要用于在图形用户界面(GUI)中创建框架,并提供各种边框样式和功能。它是Qt中一个基础的容器类,也是许多基础控件的基类,可以被QLCDNumber、QToolBox、…

数据重塑:长宽数据转换【基于tidyr】

在数据分析和可视化过程中,数据的组织形式直接影响着我们能够进行的分析类型和可视化效果。这里简单介绍两种常见的数据格式:长格式(Long Format)和宽格式(Wide Format),以及如何使用tidyr包进行…

【网络】应用层——HTTP协议

> 作者:დ旧言~ > 座右铭:松树千年终是朽,槿花一日自为荣。 > 目标:了解什么是HTTP协议。 > 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安! > 专栏选自:网络 &g…

【安全测试】sqlmap工具(sql注入)学习

前言:sqimap是一个开源的渗透测试工具,它可以自动化检测和利用SQL注入缺陷以及接管数据库服务器的过程。它有一个强大的检测引擎,许多适合于终极渗透测试的小众特性和广泛的开关,从数据库指纹、从数据库获 取数据到访问底层文件系…

【Android】webview常用方法和使用

文章目录 前言一、常见用法二、基础属性webView的常用方法WebViewClient的常用方法WebChromeClient的常用方法WebSettings的相关方法 三、加载流程和事件回调四、webview和JS之间的互相调用总结 五、参考链接 前言 最近项目又用到了webview,在回顾复习一次webview相…

可编辑PPT | 指挥中心系统建设与应用方案

本方案是一份全面的指挥中心系统建设与应用方案,涵盖了建设方案分析、指挥调度、远程通讯、会务管理等多个方面,旨在通过整合语音、视频监控、会议、指挥调度等多种技术,构建一个现代化、网络化、智慧化的城市指挥中心,以提高应对…

计算机新手练级攻略——善用搜索引擎

计算机学生新手练级攻略——善用搜索引擎 在信息爆炸的时代,计算机专业的学生如何有效地自我提升?答案可能就藏在一个简单却强大的工具——搜索引擎中。搜索引擎不仅是获取知识的入口,更是解决问题的利器。下面,我将分享一些善用搜…

vs2019托管调试助手 “ContextSwitchDeadlock“错误

错误描述 托管调试助手 "ContextSwitchDeadlock":“CLR 无法从 COM 上下文 0xd183e0 转换为 COM 上下文 0xd18328,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长…

【ARM】MDK-烧录配置文件无权限访问

【更多软件使用问题请点击亿道电子官方网站】 1、 问题场景 客户代码编译正常、调试出现报错<Error: Flash Download failed - "Cortex-M4"> 仿真器识别正常&#xff0c;keil-Debug内显示相关信息、设备启动正常。 记录排查步骤&#xff0c;找到配置文件位…

【C语言刷力扣】66.加一

题目&#xff1a; 解题思路&#xff1a; 最初思路是打算将数组中的数提出来&#xff0c;加一&#xff0c;再放回另一数组中。后来发现数组最大长度100&#xff0c;而100位的数字太大了。 所有在数组上实现加一。 利用 carry 标记每一位是否进位&#xff0c;即该位数加 carry &a…

Docker使用docker-compose一键部署nacos、Mysql、redis

下面是一个简单的例子&#xff0c;展示如何通过Docker Compose文件部署Nacos、MySQL和Redis。请确保您的机器上已经安装了Docker和Docker Compose。 1&#xff0c;准备好mysql、redis、nacos镜像 sudo docker pull mysql:8 && sudo docker pull redis:7.2 &&…

【LLM】3:从零开始训练大语言模型(预训练、微调、RLHF)

一、 大语言模型的训练过程 预训练阶段&#xff1a;PT&#xff08;Pre training&#xff09;。使用公开数据经过预训练得到预训练模型&#xff0c;预训练模型具备语言的初步理解&#xff1b;训练周期比较长&#xff1b;微调阶段1&#xff1a;SFT&#xff08;指令微调/有监督微调…

YOLO即插即用---PConv

Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks 论文地址&#xff1a; 1. 论文解决的问题 2. 解决问题的方法 3. PConv 的适用范围 4. PConv 在目标检测中的应用 5. 评估方法 6. 潜在挑战 7. 未来研究方向 8.即插即用代码 论文地址&#xff1a; …

Fortran安装(vscode+gcc+Python)

编写时间&#xff1a; 2024年11月7日 环境配置&#xff1a; gcc VScode Python 条件&#xff1a; Windows 10 x64 VMware虚拟机 前言 这是我出的第2个关于Fortran安装的教程&#xff0c;由于上一个方法&#xff08;你可以在本专栏里找到&#xff09;对储存空间的要求比较…

ModuleNotFoundError: No module named ‘_ssl‘ centos7中的Python报错

报错 ModuleNotFoundError: No module named ‘_ssl’ 解决步骤&#xff1a; 1.下载openssl wget https://www.openssl.org/source/openssl-3.0.7.tar.gz tar -zxvf openssl-3.0.7.tar.gz cd openssl-3.0.72.编译安装 ./config --prefix/usr/local/openssl make make install3…

TensorFlow|猫狗识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 要求&#xff1a; 了解model.train_on_batch()并运用了解tqdm&#xff0c;并使用tqdm实现可视化进度条 &#x1f37b; 拔高&#xff08;可选&#xff09;&…