API 26 adds new option Bitmap.Config.HARDWARE:



文档中未解释的问题:

  • 我们是否应该始终现在选择Bitmap.Config.HARDWARE而不是
    当速度是最高优先级和质量时的Bitmap.Config.RGB_565和可变性不是吗(例如,缩略图等)?
  • 使用此选项解码后的像素数据实际上不是吗
    消耗任何堆内存并且仅驻留在GPU内存中?如果是这样,这似乎
    最终缓解了OutOfMemoryException的顾虑
    处理图像。
  • 与RGB_565,RGBA_F16或ARGB_8888相比,我们应该期待什么质量?
    从这个选项?

  • RGB_565解码?
  • (感谢@CommonsWare在评论中指向它)
    如果使用此解码图像时我们超过了GPU内存,则会发生这种情况
    选项?会抛出一些异常(也许是相同的OutOfMemoryException :)吗?
  • 最佳答案

    文档和公共(public)源代码尚未推送到Google's git。因此,我的研究仅基于部分信息,一些实验以及我自己将JVM移植到各种设备上的经验。

    我的测试创建了一个大型可变位图,然后单击按钮将其复制到新的硬件位图中,然后将其添加到位图列表中。在崩溃之前,我设法创建了多个大位图实例。

    我能够在android-o-preview-4 git push中找到它:

    +struct AHardwareBuffer;
    +#ifdef EGL_EGLEXT_PROTOTYPES
    +EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
    +#else
    +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);
    

    然后寻找documentation of AHardwareBuffer,并在Android共享内存(“ashmem”)中创建由 EGLClientBuffer (本 map 形缓冲区)支持的ANativeWindowBuffer。但是实际的实现可能会因硬件而异。

    关于这些问题:



    对于SDK> = 26,HARDWARE配置可以通过避免每次将相同的位图返回到屏幕时将像素数据复制到GPU来改善低级位图的绘制。我猜它可以防止在将位图添加到屏幕时丢失某些帧。

    内存不计入您的应用程序,我的测试证实了这一点。

    native 库文档说如果内存分配不成功,它将返回null
    如果没有源代码,目前尚不清楚Java实现(API实现者)在这种情况下会做什么-它可能决定将OutOfMemoryException或fallback投向其他类型的分配。

    更新:实验表明没有抛出OutOfMemoryException。分配成功后-一切正常。分配失败后,模拟器崩溃(刚消失)。在其他情况下,在应用程序内存中分配位图时,我会收到奇怪的NullPointerException

    由于不可预测的稳定性,我不建议在当前的生产环境中使用此新API。至少并非没有大量测试。



    像素数据将在共享内存(可能是纹理内存)中,但是Java中仍然有一个小的Bitmap对象引用它(因此“ANY”是不准确的)。

    每个供应商都可以决定以不同的方式实现实际分配,这不是他们所绑定(bind)的公共(public)API。
    因此OutOfMemoryException可能仍然是一个问题。我不确定如何正确处理它。


    HARDWARE标志与质量无关,而与像素存储位置有关。由于配置标志不能为OR编码,因此我假设将默认(ARGB_8888)用于解码。

    (实际上,HARDWARE枚举对我来说似乎是一种hack)。


    HARDWARE标志似乎与解码无关,因此与ARGB_8888相同。



    内存快用完时,我的测试结果很糟糕。
    模拟器有时会崩溃,而在其他情况下,我遇到了意外的无关的NPE。没有OutOfMemoryException发生,也没有办法告诉GPU内存何时耗尽,因此没有办法预见到这一点。

    09-11 17:06