【问题标题】:"Canvas: trying to draw too large bitmap" when Android N Display Size set larger than SmallAndroid中的“画布:试图绘制太大的位图”并且显示尺寸设置为大于小
【发布时间】:2016-12-30 21:02:53
【问题描述】:

当新引入的Display size OS 设置设置为太大时,我有一个已发布的应用程序在 Android N 上启动时崩溃。

当我查看 logcat 时,我看到以下消息:

java.lang.RuntimeException: Canvas: trying to draw too large(106,975,232 bytes) bitmap.

我在我的第一个 Activity 中将问题追溯到一个 ImageView,它显示了一个漂亮的大背景图像。有问题的图像为 2048x1066,位于我的通用 drawables 目录中,因此无论密度如何,都将使用此图像。

Display size 设置为Small 时,一切正常。但是当我上升到Default 时,它停止工作。如果我然后将图像换成较小的图像,它可以在Default 工作,但如果我升级到Large,它会再次停止工作。

我的猜测是,向上调整 Display size 会使您的设备表现得像一个物理上更小但像素密度更高的设备。但我不明白我应该在这里做什么。如果我将逐渐变小的图像放入越来越高的分辨率,那么它在真正的大显示器上看起来并不好。还是我不明白什么?

任何指针将不胜感激。

【问题讨论】:

  • "有问题的图像是 2048x1066 并且在我的通用 drawables 目录中,所以无论密度如何,都会使用这个图像" -- res/drawable/res/drawable-mdpi/ 的同义词。如果您不希望图像根据密度进行缩放,use res/drawable-nodpi/ or res/drawable-anydpi/
  • “你是说一个 100x100 像素的图像存在于各种不同的资源目录中,实际上是在进行布局之前对其进行缩放以创建一个不同分辨率的虚拟版本?” - 这取决于您拥有的密度和运行的设备。如果存在完全匹配,则不会重新采样。如果不完全匹配,则重新采样附近密度的图像。所以,如果你只有res/drawable/foo.png(又名res/drawable-mdpi/foo.png),而你的设备是xhdpi,图像将沿两个轴翻倍,占用4倍内存。
  • 错误中的 106975232 值恰好是图像分辨率的 49 倍,这意味着沿两个轴进行了 7 倍的重采样。这比我预期的要高得多。我还没有机会使用 Android 7.0 中的显示尺寸设置,所以我将把它添加到我不断增长的待办事项列表中......
  • 在 49 倍上不错!我想我可以解释为什么它这么高。请记住,该数字是字节。该图像是 24 位的,但它可能以每像素 32 位的速度读入。这将使其在内存中为 8732672 字节,恰好是该数字的 12.25 倍,这反过来意味着沿每个轴缩放 3.5 倍。这个设备是 xxhdpi,所以看起来它可能是正确的。无论哪种方式,我都不知道资源会像这样被重新采样。感谢您的帮助! (顺便说一句,将图像移动到 drawable-nodpi 确实可以解决它。)
  • 你真的应该接受约翰的回答

标签: android layout android-7.0-nougat


【解决方案1】:

我的情况是,将(高分辨率)启动位图从 drawable 移动到 drawable-xxhdpi 是解决方案。

我遇到了同样的问题。我没有怀疑我的启动画面是问题所在,因为它在应用程序启动时显示,但事实证明启动画面是问题所在。

在我的例子中,启动画面的分辨率为 xxhdpi,它被错误地放置在 drawable 文件夹中,而不是 drawable-xxhdpi。这使得 Android 假设初始屏幕具有 mdpi 分辨率并将图像缩放到所需大小的 3*3 倍并尝试创建位图。

【讨论】:

  • 我猜:所以,android 将图像从 xxhdpi 缩放到 hdpi 以成为更轻的图像?正如你所说的,例如从 3*3 -> 1/1 到 1/3?
  • 正如 kalsara Magamage 所说,现在是 mipmap-xxhdpi。
【解决方案2】:

android: 行之间的 Manifest 文件的应用程序标记中添加以下代码后,我解决了这个问题。

android:hardwareAccelerated="false"

【讨论】:

  • 好吧,花了几个小时后,这个解决方案适用于小米和三星的移动问题。
  • 这将导致禁用 CardView 的所有高度。所以正确的解决方案是将位图缩放到更小的尺寸。
  • 与其在Application级别禁用硬件加速,在Activity、Window、View级别控制它会更有用。
  • 但是,在执行android:hardwareAccelerated="false" 之后还有一些其他问题。在 API 级别低于 22 的某些设备中显示奇怪的视图。
  • 不要这样做,它会减慢您的应用速度。
【解决方案3】:

我不知道它会对某些人有帮助,但我就把它留在这里。 就我而言 - 问题仅出现在装有 Android 7 的 Sumsung 设备上,问题出在启动画面的比例上。将高度更改为 1024 像素后 - 一切正常

【讨论】:

  • 我的问题是可绘制(无后缀)文件夹中的位图(jpg、png)。这是我的愚蠢,但也许它可以帮助某人:-)
  • 这很有帮助!只有三星有同样的问题......你首先遇到了什么,你是如何解决的?
  • 您是否尝试从 URL 加载图像。我在 Android 7 上仅使用三星 Galaxy S6 时遇到了同样的问题。我在 RecyclerView 中加载图像。我仍然无法弄清楚这一点。 @M'hamed
  • 我在一些 SAMSUNG S6、S6 Active 和 Android 7 上遇到了这个问题。所以我用 Firebase 进行了进一步分析,发现所有这些设备的 DPI 设置都高于 500。然后我找到了一种方法在模拟器中重现这个(我在这里使用了 MEMU),我将我的模拟器设置为与 Galaxy S6“2560x1440,DPI 577”完全相同的屏幕分辨率,我的应用程序按预期产生错误。这是由高 DPI 引起的,许多 SAMSUNG 设备都有高 DPI 设置。我将高分辨率位图图像放在“可绘制”中,它仅适用于 DPI 小于 500 的设备。将它们移动到“-xxhdpi-v4”是解决方法。
【解决方案4】:

将drawable中的图像移动到mipmap-xxhdpi。你的图像是位图格式,所以你应该把你的图像放在mipmap文件夹中,然后它就可以工作了

【讨论】:

  • AFAIK mipmap 文件夹仅用于启动器图标。我从来没有将它用于其他任何事情。见stackoverflow.com/a/28065664/4034572
  • 是的,这对我有用。我有大约 1MB 的图像大小,我把它们放在 mipmap-xxhdpi
【解决方案5】:

尝试使用 Bitmap.Factory 类,这个链接会帮助你 Loading Large Bitmaps Efficiently

【讨论】:

    【解决方案6】:

    在某些情况下,需要将原始位图绘制到 ImageViews、照片编辑应用程序等中......,

    如上所述的海湾设置

    android:hardwareAccelerated="false"
    

    会导致不好的UI体验,你可以设置hardwareAccelerated 只选择一个要绘制高分辨率图像的Activity

    <application android:hardwareAccelerated="true">
        <activity ... />
        <activity android:hardwareAccelerated="false" />
    </application>
    

    【讨论】:

      【解决方案7】:

      如果你用 Picasso 改成这样的 Glide。

      删除毕加索

      Picasso.get().load(Uri.parse("url")).into(imageView)
      

      改变滑行

      Glide.with(context).load("url").into(imageView)
      

      更高效

      【讨论】:

      • 即使从 Picasso 切换到 Glide 后,我仍然会收到错误消息。在三星 J6 手机上。还有 Moto Z2 :(
      • Glide 确实比毕加索有一些好处,例如速度,但毕加索没有坏,所以你不能建议另一个图书馆来解决它的 1 个问题。我们甚至不确定这是毕加索的问题还是它只是出现在毕加索堆栈跟踪中
      【解决方案8】:

      图标文件太大,Android 无法高效流畅地加载。 Android 可以通过其智能算法识别这一点。

      您可以使用 asystat 的Final Android Resizer 调整图标文件的大小。将它们调整为“xhdpi”或更低。

      将调整大小的照片放入可绘制或覆盖现有大图标文件。

      那么,你就完成了。

      【讨论】:

        【解决方案9】:

        如果您使用 glide 并且一次加载 1k 图像或一些图像,那么这是 glide 或您正在做的任何事情来设置图像视图的问题。你可以通过在 glide 中应用 scale 类型来解决它。

        【讨论】:

          【解决方案10】:

          就我而言,我只是使用 Paint3d 更改了在背景中使用的图像画布(或者您可以使用任何其他画布)。 Here I am sharing a screenshot just go through it.

          【讨论】:

          • 请使用 cmets 分享您的想法。
          【解决方案11】:

          通过将图像调整为较小的尺寸来解决。

          【讨论】:

            【解决方案12】:

            需要在 android 之间添加 Manifest 文件的 application 标签:添加以下行。

            android:hardwareAccelerated="false"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-03-11
              • 2020-03-22
              • 1970-01-01
              • 1970-01-01
              • 2018-07-29
              • 2012-05-11
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多