【问题标题】:Enormous memory (native heap) increase setting a layout巨大的内存(本机堆)增加设置布局
【发布时间】:2012-07-03 15:17:01
【问题描述】:

当我预计增加约 0.1 MB 时,我发现本机堆使用量增加了 6 MB

我是如何得出这些数字的:

Log.d("test", "before setting layout");
showMemoryStats();

setContentView(R.layout.my_layout);

Log.d("test", "after setting layout");
showMemoryStats();

showMemoryStats 在哪里:

public static void showMemoryStats() {
    Log.i("test", "----------------------------------------------------------------------------------------------------------------------------");
    Log.i("test", "showing memory stats in xx");
    double nativeUsage = Debug.getNativeHeapAllocatedSize(); 
    Log.i("test", "nativeUsage: " + nativeUsage);
    //current heap size 
    double heapSize =  Runtime.getRuntime().totalMemory();
    Log.i("test", "heapSize: " + heapSize);
    //amount available in heap 
    double heapRemaining = Runtime.getRuntime().freeMemory();   
    Log.i("test", "heapRemaining: " + heapRemaining);
    double memoryAvailable = Runtime.getRuntime().maxMemory() - (heapSize - heapRemaining) - nativeUsage;
    Log.i("test", "memoryAvailable: " + memoryAvailable);
    Log.i("test", "----------------------------------------------------------------------------------------------------------------------------");
}

输出:

07-03 16:50:40.127: D/test(18647): 设置布局之前

07-03 16:50:40.127: I/test(18647): ------------------------------- -------------------------------------------------- -------------------------------------------------------

07-03 16:50:40.127: I/test(18647): 显示 xx 中的内存统计信息

07-03 16:50:40.127: I/test(18647): nativeUsage: 5706008.0

07-03 16:50:40.127: I/test(18647): heapSize: 4905968.0

07-03 16:50:40.127: I/test(18647): heapRemaining: 1815456.0

07-03 16:50:40.127: I/test(18647): memoryAvailable: 2.4757912E7

07-03 16:50:40.127: I/test(18647): ------------------------------- -------------------------------------------------- -------------------------------------------------------

07-03 16:50:40.348: D/dalvikvm(18647): GC_EXTERNAL_ALLOC 释放 100K,49% 释放 2924K/5639K,外部 0K/0K,暂停 45ms

07-03 16:50:40.518: D/dalvikvm(18647): GC_EXTERNAL_ALLOC 释放 9K,49% 释放 2917K/5639K,外部 2700K/3371K,暂停 51ms

07-03 16:50:40.638: D/dalvikvm(18647): GC_EXTERNAL_ALLOC 释放 4K,49% 释放 2928K/5639K,外部 3952K/4356K,暂停 51ms

07-03 16:50:40.698: D/dalvikvm(18647): GC_EXTERNAL_ALLOC 释放 2K,48% 释放 2933K/5639K,外部 5963K/6027K,暂停 24ms

07-03 16:50:40.718: D/test(18647): 设置布局后

07-03 16:50:40.718: I/test(18647): ------------------------------- -------------------------------------------------- -------------------------------------------------------

07-03 16:50:40.718: I/test(18647): 显示 xx 中的内存统计信息

07-03 16:50:40.718: I/test(18647): nativeUsage: 1.2101904E7

07-03 16:50:40.718: I/test(18647): heapSize: 4734944.0

07-03 16:50:40.718: I/test(18647): heapRemaining: 1716432.0

07-03 16:50:40.718: I/test(18647): memoryAvailable: 1.8434016E7

07-03 16:50:40.718: I/test(18647): ------------------------------- -------------------------------------------------- -------------------------------------------------------

数学:

12101856 字节 - 5703424 字节 = 6398432 字节 = 6.10202 mb

我浏览了我的布局文件并添加了所有使用的可绘制对象的大小,总大小为 124 kb -> 0.121094 mb

那么到底是什么导致本机堆增加 6 mb?

我可以放布局文件,如果有人要求,不知道是否有意义...只是一堆带有 id 和 drawable 的布局,正如我所说的,我已经检查了 drawable 的大小。

提前非常感谢...

编辑:在我的情况下,这是解决方案 - 为了总结响应和 cmets:我将图像存储在“drawable”文件夹中并使用 hdpi 设备。解决方案:将图像放在文件夹 drawable-hdpi 中。原因:系统正在从“可绘制”中拉伸我的图像以匹配 hdpi 分辨率,尽管它们已经是 hdpi 分辨率。这使得它们占用的内存超过了应有的 2 倍。

【问题讨论】:

  • 您是否正在使用可能使用更多内存的东西填充可绘制对象?你的drawable是什么?图片还是字段?
  • 可绘制对象是位图或 XML 文件,它们引用位图来表示按下/可绘制状态。而已。填充:我正在填充动态数据,但在这些行之后。如您所见,有一个输出,然后是 setContentView,然后再次输出,中间没有其他内容。

标签: android android-layout memory


【解决方案1】:

嗯,位图占用了大量空间。

每个像素需要 4 个字节!

所以 1M 像素的图像是 4MB !!!我假设您使用了许多较小的图像,但它们很快就会加起来。

解决此问题的一种方法是以较低的分辨率加载位图(在大多数情况下,您不会注意到任何差异,因为它们无论如何都不会以最大分辨率显示)。为此请查看BitmapFactory.Options.inSampleSize

引用自 android

位图占用大量内存,尤其是对于像这样的丰富图像 照片。例如,Galaxy Nexus 上的相机拍摄照片 高达 2592x1936 像素(5 兆像素)。如果位图配置 使用的是 ARGB_8888(从 Android 2.3 开始的默认值)然后 将此图像加载到内存中大约需要 19MB 内存(2592*1936*4 字节),立即耗尽某些设备上的每个应用程序的限制。

Here is a great link to explain it better.

【讨论】:

  • 我明白了,很有趣。我会寻找解决方案。当我进步一点时回到这个线程......现在谢谢和+1
  • @Ixx 干杯。解决方案在给定的链接中。特别是第一课。它有很棒的代码 sn-ps,我也用它来缩小图像。您将所需的图像大小传递给它,它会计算并使用BitmapFactory.Options.inSampleSize 适当地缩小它。
  • 我还必须考虑回收和其他技巧,因为我会到处加载很多不同的东西......这只是开始......但是是的,缩小规模是个好主意,只要它看起来仍然完美,否则我会在这里遇到问题......
  • 好的,所以我现在有一个 480 x 800 像素的 png,这是视图/屏幕大小(我将它用作活动的背景)。所以它是图像上的 1:1 像素和屏幕上的像素,还是我错了?它占用 4 mb 空间。有没有办法在不丢失屏幕细节的情况下减小尺寸?我的意思是,我从图像中减少的每个像素都会在屏幕上丢失,因为 1:1(抱歉重复评论)。
  • @Ixx 这样大小的图像只需要 1.5MB。 (480x800x4 Bytes)。根据您需要的颜色有多丰富,您可以改用ARGB_4444。这再次将尺寸减半,但也大大减少了您可以使用的颜色数量。如果你不需要透视,我假设你不会有背景,然后使用RGB_256。这为您提供了大量的颜色,并且比其他颜色存储得少。 - 一个明确的必须
【解决方案2】:

问题是当android必须在屏幕上绘制你的drawable时,它们比它们在你的res文件夹中要大得多。例如,如果您有一个 100 Kb 的 PNG,那么这就是压缩后的大小。当 android 在屏幕上绘制 PNG 时,它会将其放大到默认大小(4 字节)*(像素高度)*(像素宽度)的正常大小。这是因为它为图像的每个像素存储 4 个字节的颜色信息。这意味着如果您的图像是例如 800 x 600 像素,那么 android 生成的结果位图是 800x600x4 字节 = 1920000 字节 = 接近 2 Mb。

如果你想解决这个问题,你必须使用更小的图片。

【讨论】:

  • 好的,所以我现在有一个 480 x 800 像素的 png,这是视图/屏幕大小(我将它用作活动的背景)。所以它是图像上的 1:1 像素和屏幕上的像素,还是我错了?它占用 4 mb 空间。有没有办法在不丢失屏幕细节的情况下减小尺寸?我的意思是,我从图像中减少的每个像素都会在屏幕上丢失,因为 1:1(抱歉重复评论)。
  • @Doomsknight 已经非常准确地解释了它。奇怪的是你的大小是 4 MB。你从哪里得到这个号码?
  • 嗨。我用 2 个 480 x 800 的 png 图像进行了测试。一个有透明区域,另一个没有。没有透明区域的图像有 1.7 mb,另一个有 3.456 mb(它是前 4 个,因为它有点大,按比例缩小)。我通过background = ((BitmapDrawable)myRootView.getBackground()).getBitmap(); Log.d("test", "size of img: " + (background.getRowBytes() * background.getHeight() / 1000000d)); 得到了它,并且还跟踪了本机堆大小。
  • 如果你用 getByteCount() 代替,然后除以 1024 * 1024(一千字节等于 1024 字节),你会得到什么? background = ((BitmapDrawable)myRootView.getBackground()).getBitmap(); Log.d("test", "size of img: " + (background.getByteCount() / 1048576d));
  • background.getByteCount() 仅适用于 API 级别 12 及以上。如果可以的话,它绝对是一个更好的选择。还可以尝试记录 background.getHeight()background.getWidth() 以查看读取时的实际高度和宽度。
猜你喜欢
  • 2023-03-03
  • 2019-03-28
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 2017-03-09
  • 1970-01-01
  • 2013-09-15
相关资源
最近更新 更多