如果不小心,使用图片时可能会快速引入性能问题。使用大型位图时,您很容易遇到 OutOfMemoryError
。遵循以下最佳实践可以确保您的应用达到最佳性能。
请仅加载所需大小的位图
大多数智能手机都自带高分辨率相机,能够生成非常大的图片文件。如果您要在屏幕上显示图片,则必须降低图片的分辨率,或者仅加载不超过图片容器大小的图片。持续加载超过所需大小的图片可能会耗尽 GPU 缓存,从而导致界面渲染性能不佳。
如需管理图片大小,请执行以下操作:
- 尽可能缩小图片文件(而不影响输出图片)。
- 请考虑将图片转换为 WEBP 格式,而不是 JPEG 或 PNG。
- 针对不同的屏幕分辨率提供较小的图片(请参阅提示 3)。
- 使用图片加载库,该库会按比例缩小图片的大小,以适应屏幕上的视图大小。这有助于提高屏幕的加载性能。
尽可能使用矢量而非位图
以视觉方式表示屏幕上的内容时,您需要确定它是否可以表示为矢量。首选矢量图像而非位图,因为矢量图像在缩放为不同的大小时不会像素化。不过,并非所有内容都可以表示为矢量。比如说,使用相机拍摄的图片就无法转换为矢量。
针对不同屏幕尺寸提供备用资源
如果您要在应用中提供图片,请考虑为不同的设备分辨率提供不同大小的资源。这有助于缩减应用在设备端的下载大小,并提高性能,因为这会在分辨率较低的设备上加载分辨率较低的图片。如需详细了解如何针对不同设备尺寸提供备用位图,请查看备用位图文档。
使用 ImageBitmap
时,在绘制前调用 prepareToDraw
使用 ImageBitmap
时,如需开始将纹理上传至 GPU,请先调用 ImageBitmap#prepareToDraw()
,然后再实际开始绘制。这有助于 GPU 准备纹理并提升在屏幕上显示视觉效果的性能。大多数图片加载库都已经执行此项优化,但如果您要自行使用 ImageBitmap
类,请谨记这一要点。
最好将 Int
DrawableRes
或网址作为参数(而不是 Painter
)传递给可组合项
由于处理图片的过程非常复杂(例如,为 Bitmaps
编写 equals 函数的计算开销非常大),因此 Painter
API 未明确标记为稳定的类。不稳定的类可能会导致不必要的重组,这是因为编译器无法轻松推断数据是否发生了更改。
因此,最好是将网址或可绘制对象资源 ID 作为参数传递给可组合项,而不是传递 Painter
作为参数。
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
避免位图在内存中存储的时间超过所需要的时间
加载到内存中的位图越多,设备上内存耗尽的可能性就越高。例如,如果要在屏幕上加载 Image 可组合项的大型列表,请使用 LazyColumn
或 LazyRow
,以确保在滚动大型列表时释放内存。
请勿将大型图片与 AAB/APK 文件打包在一起
导致应用下载大小较大的一个主要原因就是在 AAB 或 APK 文件中打包了图形。使用 APK 分析器工具确保打包的文件大小未超过所需的图片文件大小。请缩减图片大小或考虑将图片放置在服务器上,并仅在需要时下载这些图片。
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- ImageBitmap 与 ImageVector {:#bitmap-vs-vector}
- 在 Compose 中保存界面状态
- Jetpack Compose 的阶段