如果您不小心,处理图像可能会很快导致性能问题。在处理大型位图时,您很容易遇到 OutOfMemoryError
。请遵循以下最佳实践,以确保您的应用获得最佳性能。
仅加载您需要的位图大小
大多数智能手机都配备了高分辨率摄像头,可以生成大型图像文件。如果您在屏幕上显示图像,则必须降低图像分辨率或仅将图像加载到图像容器的大小。持续加载比需要更大的图像可能会耗尽 GPU 缓存,导致 UI 渲染性能下降。
要管理图像大小
- 将图像文件缩小到尽可能小(不会影响输出图像)。
- 考虑使用 将图像转换为 WEBP 格式而不是 JPEG 或 PNG。
- 为不同的屏幕分辨率提供较小的图像(请参阅 提示 #3),
- 使用 图像加载库,它会将图像缩小以适合屏幕上视图的大小。这有助于提高屏幕的加载性能。
尽可能使用矢量而不是位图
在屏幕上视觉表示某些内容时,您需要确定它是否可以用矢量表示。优先使用矢量图像而不是位图,因为它们在缩放至不同大小后不会出现像素化。但是,并非所有内容都可以表示为矢量 - 用相机拍摄的图像无法转换为矢量。
为不同的屏幕尺寸提供替代资源
如果您正在随应用一起提供图像,请考虑为不同的设备分辨率提供不同尺寸的资源。这有助于减少设备上应用的下载大小,并提高性能,因为它将在低分辨率设备上加载低分辨率图像。有关为不同设备尺寸提供替代位图的更多信息,请查看替代位图文档。
使用 ImageBitmap
时,在绘制之前调用 prepareToDraw
使用 ImageBitmap
时,要开始将纹理上传到 GPU 的过程,请在实际绘制之前调用 ImageBitmap#prepareToDraw()
。这有助于 GPU 准备纹理并提高屏幕上显示视觉效果的性能。大多数图像加载库已经进行了此优化,但如果您自己使用 ImageBitmap
类,则需要注意这一点。
优先将 Int
DrawableRes
或 URL 作为参数传递到您的可组合项中,而不是 Painter
由于处理图像的复杂性(例如,为 Bitmaps
编写 equals 函数在计算上将非常昂贵),因此 Painter
API 明确地没有标记为 稳定 类。不稳定的类会导致不必要的重新组合,因为编译器无法轻松推断数据是否已更改。
因此,最好将 URL 或可绘制资源 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 中保存 UI 状态
- Jetpack Compose 阶段