0

原本一切都很好。我一直在使用 5 个可绘制目录

drawable-hdpi
drawable-ldpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi

这是我最近创建一个新项目时由 eclipse adt-bundle 为我创建的。因此,当我需要一个新的位图时,我一直将位图的副本放入这 5 个目录中的每一个中。这对我来说总是有点奇怪,所以我很高兴通过阅读Android 文档提供资源发现我可以为所有常见的位图提供一个“可绘制”的单一目录。所以我切换到

drawable
drawable-hdpi
drawable-ldpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi

原始 5 个目录中剩下的唯一文件是最初创建项目时为我创建的“ic_launcher.png”文件。

但是,可绘制目录的新配置严重失败。加载 36k 位图文件 frame.png,现在由于该行而发生内存不足错误

 bitmap_fancyframe = BitmapFactory.decodeResource(getResources(), R.drawable.frame);

logcat 显示 Android 现在尝试分配一个 6790156 字节的内存块,结果该行(即 logcat 底部提到的 DrawOnTop.java:95 行)

06-01 07:26:53.995: I/dalvikvm-heap(1530): Forcing collection of SoftReferences for 6790156-byte allocation
06-01 07:26:54.025: D/dalvikvm(1530): GC_BEFORE_OOM freed 9K, 14% free 53820K/62343K, paused 27ms, total 27ms
06-01 07:26:54.025: E/dalvikvm-heap(1530): Out of memory on a 6790156-byte allocation.
06-01 07:26:54.025: I/dalvikvm(1530): "main" prio=5 tid=1 RUNNABLE
06-01 07:26:54.025: I/dalvikvm(1530):   | group="main" sCount=0 dsCount=0 obj=0x41077508 self=0x40de49a0
06-01 07:26:54.025: I/dalvikvm(1530):   | sysTid=1530 nice=0 sched=0/0 cgrp=apps handle=1075179312
06-01 07:26:54.025: I/dalvikvm(1530):   | schedstat=( 681383064 1229707806 4777 ) utm=53 stm=14 core=0
06-01 07:26:54.025: I/dalvikvm(1530):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
06-01 07:26:54.025: I/dalvikvm(1530):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
06-01 07:26:54.025: I/dalvikvm(1530):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:476)
06-01 07:26:54.025: I/dalvikvm(1530):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:499)
06-01 07:26:54.025: I/dalvikvm(1530):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:529)
06-01 07:26:54.025: I/dalvikvm(1530):   at com.example.MyApp.DrawOnTop.<init>(DrawOnTop.java:95)

谁能解释为什么会这样?更重要的是,该 frame.png 文件在我的代码中被缩放和拉伸,所以我真的不需要它的 5 个副本,所以有什么方法可以让我在一个“可绘制”目录中拥有所有常见的 png 位图,而无需这些类型的问题?

更新感谢@sam 的评论和@ken-wolf 的回答,我现在了解到,如果没有正确类型的位图,Android 会进行大量位图缩放。所以当我简单地在所有目录之间复制相同的位图时,我的新理解是这样做的效果是位图将被加载而不缩放。对我来说,在扩展过程中显然出了点问题,但是由于我正在自己进行扩展,所以我也不需要 Android 来做这件事。所以我现在认为重要的问题是:如何设置我的应用程序以便只提供每个位图的一个版本,并指示 Android 不要进行任何位图缩放

4

3 回答 3

3

在这里直奔问题的核心:

如何设置我的应用程序以便只提供每个位图的一个版本...

只需将您的位图放在您的一个drawable目录中。我相信它必须是一个比目标设备更小的 DPI。但随后,Android 将在内存中为具有更大 DPI 的设备创建一个缩放版本。我还相信,如果您只使用该drawable目录,Android 会假定它是中等 DPI,并且您会得到与将其放入drawable-mdpi. 请注意,缩放后的图像实际上是不同的尺寸(以像素为单位),但以英寸/DP 为单位的尺寸大致相同。在屏幕xxhdpixxxhdpi,内存中的版本最终可能会非常庞大​​。例如,我有一个来自 iPhone Retina 版本产品的 640x960 背景图像。(这可能属于hdpi我应该生成更小的版本)。如果你把它放进去drawable-mdpiAndroid 在xxhdpi设备上将其缩放 3 倍,因此最终为 1920x2880,每像素 32 位,我认为约为 22 兆。

并指示 Android 不要进行任何位图缩放。

要在加载时不进行位图缩放,请使用drawable-nodpi目录。您将不得不在绘制时或在您的布局中手动缩放(使用android:scaleType="fitXY"或类似的,如果您有任何查询图像大小的代码,它将始终返回相同的像素数。质量是难以察觉的不同(如果这是您唯一的大小)有)。性能明显更好,并且内存中没有巨大的图像,只有原始大小的图像。

于 2013-12-17T23:46:11.577 回答
1

It is good practice to provide different sized versions (actual width x height pixel sizes) of each of your images in each of the corresponding folders. This ensures that Android picks the appropriate one based on the device to deliver the sharpest image. You can put them all in the /drawable/ folder only but this will result in blurry looking images - this is especially apparent at higher densities. Give this a read again, it explains it well: Supporting Multiple Screens

The "default" resources are those that are not tagged with a configuration qualifier. For example, the resources in drawable/ are the default drawable resources. The system assumes that default resources are designed for the baseline screen size and density, which is a normal screen size and a medium density. As such, the system scales default density resources up for high-density screens and down for low-density screens, as appropriate.

As to the bitmap out-of-memory error, this is a complex issue to do with memory-allocation on Android. Unfortunately you cannot accurately tell in advance how much memory you have available, and putting Bitmaps into memory is quite expensive. Without knowing about the rest of your application it's hard to give an exact solution but there are defensive measures you can take to ensure this doesn't happen, including:

  • Making a global, static reference to a bitmap and re-using it
  • Making sure you are removing any references to that Bitmap from views and calling Bitmap.recycle() when you are done with it
  • Using a Memory Cache
于 2013-06-01T07:43:32.293 回答
1

您将位图添加到 drawable-nodpi 文件夹。如果你不想要任何缩放。或者从清单中禁用自动缩放。

http://developer.android.com/guide/practices/screens_support.html#DensityConsiderations

于 2014-05-12T21:50:28.273 回答