我们为什么应该使用硬件位图?
因为硬件位图仅储存像素数据的一份副本。一般情况下,应用内存中有一份像素数据(即像素字节数组),而在显存中还有一份副本(在像素被上传到 GPU之后)。而硬件位图仅持有 GPU 中的副本,因此:
- 硬件位图仅需要一半于其他位图配置的内存;
- 硬件位图可避免绘制时上传纹理导致的内存抖动。
目前,你可以在 Glide 请求中将默认的 设置为 DecodeFormat.PREFER_ARGB_8888
。要为应用中的所有请求都应用该操作,你需要在你的 中修改默认选项的 DecodeFormat
,详见 。
未来 Glide 将默认加载硬件位图而不需要额外的启用配置,只保留禁用的选项。
如何禁用硬件位图?
如果你需要禁用硬件位图,你应当仅在以下的一些缓慢的或根本不可用 (broken) 的情况下才尝试去做。你可以使用 来为一个特定的请求禁用硬件位图。
或直接使用 :
在显存中存储像素数据意味着这些数据不容易访问到,在某些情况下可能会发生异常。已知的情形列举如下:
- 在本地 (native) 代码中读写像素数据
- 使用软件画布 (software Canvas) 渲染硬件位图:
Canvas canvas = new Canvas(normalBitmap)
canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
- 在绘制位图的 View 上使用软件层 (software layer type) (例如,绘制阴影)
ImageView imageView = …
imageView.setImageBitmap(hardwareBitmap);
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
需要ARGB_8888 Bitmaps 作为前置条件
- 在代码中触发截屏操作,它会尝试使用 Canvas 来绘制视图层级。
作为一个替代方案,在 Android O 以上版本你可以使用 PixelCopy.
- 共享元素过渡 (shared element transition)(OMR1已修复)
以下是一个示例 trace:
使用硬件位图有什么缺点?
在某些情况下为了避免打断用户,Bitmap
类将执行一次昂贵的显存复制。在某些使用这些方法的情况下,你应该根据使用这些缓慢方法的使用频率来考虑避免使用硬件位图配置。如果你确实要使用这些方法,系统将会打印一条信息: “Warning attempt to read pixels from hardware bitmap, which is very slow operation”
,并触发一次 )。
原文: