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