【问题标题】:Huge Bitmaps causing ANR in android在android中导致ANR的巨大位图
【发布时间】:2012-03-22 21:49:02
【问题描述】:

事情是这样的:

  • 我正在使用巨大的位图 [1024 X 1024]
  • 我需要 (RGB & alpha) 格式的位图数据进行像素操作;对于这种操作,我正在使用本机库
  • Activity 适用于 [512 X 512] 图像...但是当我在具有类似任务的 Activity 之间切换时,android 崩溃并出现以下跟踪

问题是这样的:

  • 我做错了什么?什么应该导致 JiT 调整大小?
  • 有没有办法加载巨大的位图..?如果我使用应用程序缓存;在这种情况下它会给我带来一些好处吗?如果是,那么缓存会消耗哪些内存?主要是我达到了内存限制......所以我正在努力解决这个问题......

痕迹:

03-22 14:21:05.240: I/dalvikvm(105): Jit: resizing JitTable from 8192 to 16384
03-22 14:21:05.730: D/dalvikvm(196): GC_EXPLICIT freed 44K, 50% free 3130K/6151K,external 5368K/6703K, paused 713ms

请注意:

  • 我目前在 API 10 上运行 [没有使用 API 11 或更高版本的范围]
  • 我也无法使用“android:largeHeap”选项
  • 当我使用本机库时,我达到了 6 MB 的限制 [本机内存],尽管我有 32 MB 内存可供使用...

更新: [ANR 追踪]

此 ANR 跟踪指示 KeyDispatchingTimedOut .. 但我相信这不是原因...在单击“菜单”时,我正在使用 Intent 切换到另一个活动。当此活动启动时,它需要计算“背景图像”基于使用本机库的“颜色数组”......这需要很长时间...... 请注意,当单独启动活动时,会发生相同的计算...

E/ActivityManager(105): ANR in com.uc (com.uc/.UcMain)
E/ActivityManager(105): Reason: keyDispatchingTimedOut
E/ActivityManager(105): Load: 2.31 / 1.58 / 1.48
E/ActivityManager(105): CPU usage from 29434ms to 1ms ago:
E/ActivityManager(105):   97% 1737/com.uc: 97% user + 0.1% kernel / faults: 117 minor
E/ActivityManager(105):   1.4% 73/akmd: 0% user + 1.4% kernel
E/ActivityManager(105):   0.6% 105/system_server: 0.2% user + 0.3% kernel / faults: 9 minor

【问题讨论】:

  • 一张 1024x1024 RGBA 图像加载到内存时大小为 4MB。我想你应该只使用较小的图像。此外,您的跟踪没有错误。这只是关于内部的信息(尽管与内存有关)
  • 我还添加了 ANR 信息以供参考...不能选择使用较小的图像/采样...我需要全强度图像!我不确定的一件事是是否有可能直接在本机内存中创建图像?
  • 所有onCreateonClickonLocationChangedonStuffHappened,..都在UI线程中执行,你不能停止检查是否有事情发生(或者你得到keyDispatchingTimedOut)。如果您的代码中没有 ThreadAsyncTask -> 一切都是 UI 线程。您应该将所有图像加载和处理移动到AsyncTask

标签: android bitmap android-ndk java-native-interface


【解决方案1】:

ANR 并不是真正的内存问题,它是在 UI 线程(调试器中的“main”)上执行某些操作所花费的时间太长的问题。您在 UI 线程上所做的任何工作都需要快速进行,否则会触发 ANR 看门狗。您正在执行的长时间运行的进程导致需要将其放入另一个线程中。

您需要将计算背景图像的工作转移到单独的线程中。我建议您使用仅使用进度微调器加载 Activity 并启动后台线程的方法,然后您就可以实际显示 UI 隐藏微调器并显示要设置背景图像的视图。

请注意,您只能从 UI 线程对 Views 进行更改,例如调用 API View.setBackgroundDrawable(...) ,但您可以在后台线程中构造 Drawable,然后从 UI 线程进行设置。 AsyncTask 非常适合这种工作模式。 如果你不使用AsyncTask,那么你将使用API​​ Activity.runOnUiThread(...)

【讨论】:

  • 同意.. ANR 不是内存问题,但如果 UI 线程花费的时间过长,那么它应该一直失败,对吗?如果我首先调用“X 活动”它可以工作..如果我首先调用“Y 活动”它可以工作......但是如果我从其他人调用一个......ANR 发生......我已经尝试将它们运行为“ SingleInstance”模式,因为活动完全相互独立。供您参考,我已经用 ANR 跟踪更新了帖子...如果您需要更多信息,请告诉我
  • 直接启动不失败不代表没有问题,关键在于时机。 ANR 看门狗对启动 Activity 可能比后续的 Activity 更宽容。正如@zapl 指出的那样,如果您没有 Threads 或 AsynkTask,那么一切都在 UI 线程上运行。对于简单的东西,这很好,但通常您希望尽可能多地离开 UI 线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
相关资源
最近更新 更多