android finish() 方法不会从内存中清除应用程序

Posted

技术标签:

【中文标题】android finish() 方法不会从内存中清除应用程序【英文标题】:android finish() method doesn't clear app from memory 【发布时间】:2010-12-30 22:32:42 【问题描述】:

我有一个活动,我调用了 finish() 方法,但活动没有从内存中清除。

调用 finish() 后,我看到方法 onDestroy() 已成功执行(并且我清除了其中的所有变量和内容)。

应该从内存中清除它还是它是如何工作的?据我了解,活动的生命周期已完成。

如果它将应用程序保留在内存中,以便在用户第二次使用它时运行得更快,我可以将哪些类型的对象留在内存中以重复使用?如果我理解正确,我想清除 onDestroy 上的所有内容。

【问题讨论】:

“我有一个活动,我调用了 finish() 方法,但活动没有从内存中清除。” --准确地说,你是怎么确定的? 如果您使用 Eclipse 中的 DDMS,您可以调试以确保它通过 onDestroy() 运行,之后您仍然可以看到设备中的进程,甚至可以看到占用的堆大小,并且可以转储内存进行分析。如果我没记错的话,这意味着它仍在记忆中,对吗? 【参考方案1】:

android 保留进程以防用户想要重新启动应用程序,这使得启动阶段更快。该进程将不会做任何事情,如果需要回收内存,该进程将被终止。别担心 :)

【讨论】:

这是否也适用于“子活动”,意味着如果它不是我的应用程序中打开的最后一个活动?说:如果我从活动 A 打开活动 B,然后 B.finish(),Android 最终会将 B 保留在内存中,我最终是否还会在我的 hprof 转储中看到 B(以防 Android 不需要为其他地方回收内存)? 是的,活动 B 仍然是内存。只有当 Android 需要内存来做其他事情时,Activity B 才会被删除。 “不用担心将应用程序发送到后台而不是将其从内存中完全删除?”你是一个认真的程序员吗?银行或其他安全脆弱的应用程序怎么样? 如果您担心保留实例的内存使用情况,请覆盖活动/片段的 onDestory() 并清除保留在内存中的变量【参考方案2】:

最好的方法是先使用finish(),然后使用System.exit(0) 清除静态变量。它会给你一些空闲空间。

许多应用程序留下了让我生气的工作流程和变量。使用 30 分钟后内存已满,我必须运行任务管理器 - Lvl 2 清除内存

这不是我在我的应用程序中尝试了 3 年多的问题。使用Exit()后永远不会崩溃或重启

【讨论】:

这对我也有用。我有一种情况,我按正常行为按下后退按钮退出应用程序,它留下了记忆。下次我开始时,内存刚刚累积,如果我这样做了大约五次,我的堆就用完了(在测试设备上是 24MB)。单独完成()并没有完成这项工作。我怀疑我用来让用户知道我们会在那里的 Splash 活动可能以某种方式阻止了内存在退出时被回收。使用这么粗略的工具确实看起来不太熟练,但是当你关闭应用程序时,有什么区别? 我的游戏应用在初始运行时使用了 225MB。使用完成()并重新启动后,它第二次使用 400MB,运行速度明显变慢(我的三星 Galaxy Tab S2 有 524M 堆)。在其他较少堆积的设备上,它只是在第二次运行时因“内存不足”错误而崩溃。在“finish()”之后使用“System.exit(0)”似乎可以解决这个问题。我注意到'finish()' 不会立即停止代码运行,因为放在'finish()' 之后仍然会到达'System.exit(0)'。但是,“System.exit(0)”似乎确实会停止在其行运行的代码。 警告:我使用我的应用 System.exit(0) 进行测试,如果在片段上完成旋转设备后重新创建视图会出现问题 在三星 Android 5.1.1 下,当用户触发 onBackPressed(),它调用 finish(),它调用 onDestroy(),它调用 super.onDestroy() 作为其第一步时,我的应用程序可靠地因 OOM 崩溃。 super.onDestroy() 没有停止应用程序;它继续运行,如果用户从任务管理器重新启动它,它会通过onCreate() 没有释放资源,尝试分配它已经使用的位图结构。 System.exit(0) 是我为此找到的唯一解决方案。这不是记录在案的方法,但也许它正在解决操作系统的问题。 更新: Android 的默认 GC 被我的循环方法打败了,而我的循环方法没有被 Android 的 onDestroy() 阻止。即使我的应用程序 not 超级 onBackPressed()onDestroy() 也是如此。通过设置一个导致我的方法在onDestroy() 终止的标志,我显然允许GC 运行并消除OOM 崩溃的原因而无需调用System.exit(0) 一个重要的这种方法的不同之处在于应用程序的进程现在在onDestroy() 之后继续运行,而从onDestroy() 调用System.exit(0) 会杀死该进程。【参考方案3】:

尝试使用

System.exit(0);

【讨论】:

【参考方案4】:

一旦 onDestroy() 被调用,你的活动就注定失败。期间。

话虽如此,分配给您的应用程序的进程(以及因此的地址空间)可能仍在由您的应用程序的另一部分使用 - 另一个活动或服务。您的进程也可能是空的,而操作系统还没有回收它;这不是即时的。

有关详细信息,请参阅流程生命周期文档:http://developer.android.com/reference/android/app/Activity.html#ProcessLifecycle

无论如何,如果您的 Activity 重新启动,它必须再次执行整个启动序列,从 onCreate() 开始。不要假设任何东西都可以隐式重复使用。

【讨论】:

我相信这并不完全正确。我不相信 Activity 是厄运,因为有办法泄漏内存,然后 Activity 将永远存在。 即使活动泄漏内存,当操作系统终止进程时,内存也会被回收。就像您在桌面操作系统上终止进程一样。【参考方案5】:

如果您需要从子活动中关闭应用程序,我可能会建议您这样做: 1) 从活动A调用活动B作为startActivityForResult(intent, REQUEST_CODE);

Intent intent = new Intent()
            .setClass(ActivityA.this, ActivityB.class);
            startActivityForResult(intent, REQUEST_CODE);

2) 在活动 A 中您应该添加方法:

protected void onActivityResult(int requestCode, int resultCode,
        Intent data) 
    if (requestCode == REQUEST_CODE) 
        if (resultCode == RESULT_CLOSE_APPLICATION) 
            this.finish();
        
    

3) 在活动 B 中调用完成:

this.setResult(RESULT_CLOSE_APPLICATION);
this.finish();

【讨论】:

【参考方案6】:

作为一种快速修复,您可以使用以下方法杀死您的应用:

android.os.Process.killProcess(android.os.Process.myPid());

但我不建议将其用于商业应用,因为它违背了 Android 内存管理系统的工作原理。

【讨论】:

【参考方案7】:

根据来自 Google I/O 2008 的this 介绍,Finish 应该也会导致进程被终止,但我编写了一个快速应用程序来测试这一点,而在 Android 1.5 上它不会。

正如 Romain 所说(顺便说一下,他是一名 Android 的 UI Toolkit 工程师),您的进程无论如何都会坐在那里无所事事,因此无需担心。

【讨论】:

以上是关于android finish() 方法不会从内存中清除应用程序的主要内容,如果未能解决你的问题,请参考以下文章

调用 finish() 不会清除对 Activity 的内存引用

android开发 怎么释放activity的全部内存

Android中返回Activity的两种方法

Android中的返回键和代码中的finish()之间的区别?

Android:返回上一个活动

Android:调用 Activity.finish() 方法