【问题标题】:OnDestroy not destroying objects created in OnCreateOnDestroy 不销毁在 OnCreate 中创建的对象
【发布时间】:2013-04-26 19:36:43
【问题描述】:

我有一个程序从画廊加载位图(通过调度结果意图),然后显示图像。然后在离开显示图像的活动时,我调用bm.recycle()。但这似乎并没有回收位图?我知道这是因为这里的帖子中描述的问题:android bitmap out-of-memory error after getting same image twice in a row。

这个问题具体如本题所述:为什么 onDestroy 不回收位图? (我只提供某些上下文的链接,而不是分散注意力)

这是我的 onDestroy:

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindDrawables(findViewById(android.R.id.content).getRootView());
    System.gc();
    myImage.recycle();
    myImage = null;
}

【问题讨论】:

  • 也许你只回收你创建的最后一个位图。完成后应该回收位图。
  • 完成它是指在视图中将其显示为 setImageBitmap 或 setDrawable 之后吗?
  • 不完全是,如果你这样做了,你可能会得到异常。我想说的是,不要等到你的activity进入onDestroy(),如果一个位图对你不再有用,你可以回收它。

标签: android image bitmap android-lifecycle activity-lifecycle


【解决方案1】:

您可能在某个地方有一个您忘记释放的参考。另请参阅this answer 关于如何在 Android 中查找 Memory Leak Class/Activity。我相信它会帮助您快速找到泄漏内存的位置。

还请记住,您必须自己释放内存。回调 onDestroy() 不会为您执行此操作。


首先您需要安装MAT plugin。重启后点击Dump HPROF file:

大约 30 秒后。您将看到一个对话框,您可以在其中单击完成。比你得到这个视图:

您在其中左键单击最大部分并过滤带有传出引用。然后你会在这里看到这个视图:

在这里你可以看到我错过了删除我的 ContentManager 中的项目,其中几个项目存储在我的 pending HashMap。

【讨论】:

    【解决方案2】:

    查看Android Activity Lifecycle,它显示了应该使用哪些方法来创建和释放资源。说明onCreate()对应的函数不一定是onDestroy(),因为开发者不知道Android OS什么时候会调用onDestroy()。

    答案:

    因此,在您的特定情况下,您可以在 onStop() 中释放或 recycle() Bitmap,而不是在 onDestroy() 中。

    onPause()/onResume():

    另外,最好先释放onPause()中的资源,然后在对应的方法onResume()中重新创建。

    inSampleSize 和 OutOfMemoryError:

    您还应确保使用BitmapFactory.Options.inSampleSize 打开您的Bitmap 图片尽可能小,以减少收到OutOfMemoryError 的可能性。该站点上有许多示例演示了inSampleSize 的使用。这只是其中之一:Resize picture into according to textivew's size

    Android Activity 生命周期:

    【讨论】:

    • 啊,我一直在阅读一些配对 onCreate/onDestroy 的博客
    • 不正确。 onCreate() 的反面确实是 onDestroy() - 这些方法涉及生命周期。 onStart() 的反面是 onStop(),这是一对涉及(至少部分)屏幕可见性的方法。您的困惑似乎来自应用程序在没有调用 onDestroy() 的情况下被杀死的非典型路径。
    • 在未调用 onDestroy() 的情况下,这是因为进程已被杀死,此时开发人员编写的代码既不需要也没有机会释放任何资源。如果已正确使用 Binder IPC 来通知远程对象死亡,则应释放与死进程中链接的其他进程中的远程资源。同样,操作系统级别的资源应该被进程死亡本身释放。
    • 当我将 onDestroy 更改为 onPause 时,我在 unbindDrawables(findViewById(android.R.id.content).getRootView()) 处得到一个 nullPointerException。异常说E/AndroidRuntime(3430): java.lang.RuntimeException: Unable to pause activity ... 我猜它指的是getRootView。
    • 你打电话给onPause() [不好]? onPause() 现在是否调用 super.onPause() [good] 或 super.onDestroy() [bad]?此外,一旦你recycle() 和Bitmap,你必须确保不要再次使用它,除非你重新创建它。使用isRecycled() 确定您是否尝试访问已被回收的Bitmap。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2023-04-08
    • 2017-05-23
    • 2011-06-02
    相关资源
    最近更新 更多