图片性能优化

如果不谨慎操作,处理图片可能会很快引发性能问题。处理大型位图时,您很容易遇到 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 可组合项列表,请使用 LazyColumnLazyRow 以确保在滚动大型列表时释放内存。

不要将大型图片与您的 AAB/APK 文件打包

应用下载大小过大的主要原因之一是 AAB 或 APK 文件中打包的图形。使用 APK 分析器工具确保您没有打包超出所需大小的图像文件。减小大小或考虑将图像放在服务器上,并在需要时才下载它们。