释放onPause而不是onDestroy中的资源

时间:2017-04-14 13:33:24

标签: android android-lifecycle activity-lifecycle

这是关于 POST-honeycomb (即Android 3.0+),以下引用来自https://developer.android.com/reference/android/app/Activity.html

根据生命周期,onStop和onDestroy是可以填充的,这意味着:

  

注意" Killable"上表中的列 - 用于那些方法   在该方法返回后,被标记为可填充的   主持活动的进程可能随时被系统杀死   没有执行其代码的另一行

  1. 换句话说,onStop(在此事件之前发生的其他事件)被保证被调用,但是当方法返回时,进程可能会死亡,因此onDestroy是无法保证被调用。

    另一个引用声明:

      

    对于那些未被标记为可杀戮的方法,   系统不会从系统中杀死活动的进程   调用方法的时间并在返回后继续。

    其次是

      

    因此,活动处于 killable 状态,例如,之后   onPause()到onResume()的开头。

  2. 对应上述内容,除非这只对应 PRE-honeycomb 。对于 POST-honeycomb ,情况并非如此,对吧?基本上,onPause和onStop都可以保证被调用。

  3. 假设我只在onDestroy中释放资源,那么这可能会导致泄漏,因为可能不会调用onDestroy,对吧?

  4. 然而,当进程被android本身杀死时,是否会出现除了之外的情况(即onDestroy未被调用)?是否有任何其他情况导致不会调用onDestroy,因此泄漏资源

  5. 当Android杀死资源将被破坏且不会发生泄漏(即使我们没有明确释放资源?)时,这是真的吗?

  6. 请提供详细信息,不论这些陈述是否正确(1)(2)(3)(4)(5)。

2 个答案:

答案 0 :(得分:15)

首先,让我们了解您所引用文档的内容。

以下命令显示AOSP中git blame文件的Activity.java输出:

$ cd $AOSP/frameworks/base
$ git blame ./core/java/android/app/Activity.java

输出的相关部分:

9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  363)  * <p>Note the "Killable" column in the above table -- for those methods that
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  364)  * are marked as being killable, after that method returns the process hosting the
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  365)  * activity may killed by the system <em>at any time</em> without another line
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  366)  * of its code being executed.  Because of this, you should use the
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  367)  * {@link #onPause} method to write any persistent data (such as user edits)
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  368)  * to storage.  In addition, the method
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  369)  * {@link #onSaveInstanceState(Bundle)} is called before placing the activity
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  370)  * in such a background state, allowing you to save away any dynamic instance
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  371)  * state in your activity into the given Bundle, to be later received in
550116576 (RoboErik                        2014-07-09 15:05:53 -0700  372)  * {@link #onCreate} if the activity needs to be re-created.
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  373)  * See the <a href="#ProcessLifecycle">Process Lifecycle</a>
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  374)  * section for more information on how the lifecycle of a process is tied
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  375)  * to the activities it is hosting.  Note that it is important to save
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  376)  * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState}
5c40f3fcc (Daisuke Miyakawa                2011-02-15 13:24:36 -0800  377)  * because the latter is not part of the lifecycle callbacks, so will not
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  378)  * be called in every situation as described in its documentation.</p>
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  379)  *
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  380)  * <p class="note">Be aware that these semantics will change slightly between
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  381)  * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB}
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  382)  * vs. those targeting prior platforms.  Starting with Honeycomb, an application
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  383)  * is not in the killable state until its {@link #onStop} has returned.  This
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  384)  * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  385)  * safely called after {@link #onPause()} and allows and application to safely
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  386)  * wait until {@link #onStop()} to save persistent state.</p>
0aae2d4e0 (Dianne Hackborn                 2010-12-07 23:51:29 -0800  387)  *
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  388)  * <p>For those methods that are not marked as being killable, the activity's
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  389)  * process will not be killed by the system starting from the time the method
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  390)  * is called and continuing after it returns.  Thus an activity is in the killable
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  391)  * state, for example, between after <code>onPause()</code> to the start of
9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  392)  * <code>onResume()</code>.</p>

请注意,Dianne Hackborn在2010-12-07中添加了讨论蜂窝后行为的段落,而附带的段落可以追溯到2009-03-03。

它告诉我们的是,Dianne添加了新段落而没有更新javadoc的其余部分,因此存在矛盾。不幸的是,这在Android中并不罕见。

问题:

1)在后Honeycomb版本的Android上,onResume()onStop()都可以被调用(正如Dianne Hackborn在活动&#39; javadoc中所述)。

2)在预蜂窝之前,只保证调用onPause()(如早期版本的活动&#39; s javadoc所述)

仅当托管整个应用程序的进程被终止时,才会调用

3,4,5)onDestroy()。当进程被终止时,分配给它的所有资源都被释放,因此在这种情况下不存在内存泄漏的风险。

重要提示:由于释放onDestroy()中的资源不会导致内存泄漏,因此将所有&#34;释放&#34;放在一起可能是一个好主意。代码在那里。但是,它很少是最佳方法。为什么?请阅读以下内容。

Activity转到后台时,它会停止,但不会被销毁(通常)。 Activity可以留在这个&#34;停止&#34;状态很长一段时间,如果用户返回应用程序,将再次启动。如果您在onDestroy()中释放资源(默认情况下Activity转到后台时)Activity将在处于停止状态时保留这些资源,从而导致更多的资源被你的应用程序在后台状态下使用。

当Android内存不足时,它会开始终止进程​​以释放它们消耗的内存。在选择要杀死哪些进程时考虑的最重要的考虑因素之一是它们的资源消耗。因此,如果您的应用在处于后台停止状态时保留资源,则将有更高的机会被Android杀死。

此外,我们开发人员必须确保为用户制作最好的应用。在后台使用非最少量的用户电话资源和电池的应用程序不是一个好的应用程序。用户会知道它!

因此,我强烈建议以onStop()方法释放所有资源。我通常不会覆盖onDestroy()Activities中的Fragments方法。

推论:正如@Juan在评论中指出的那样,上面重要的注释具有同样重要但不那么明显的推论:onStart()应该是资源的唯一方法正在分配。无论您对&#34;资源&#34;的定义是什么是的,onCreate()onResume()都不应该分配这些资源。

答案 1 :(得分:2)

我认为瓦西里提供了一个很好的答案。

还有一个小而重要的缺点
  
      
  1. 当Android杀死进程时,资源将被销毁并且不会发生泄漏(即使我们没有明确释放资源吗?)这是真的吗?。
  2.   

答案取决于你究竟害怕什么。正如Vasily所指出的,Android(基于Linux)是一个现代安全的操作系统,它保证当进程被终止时,所有内存都将被释放,而且所有打开的文件,网络连接等也将被正确关闭。因此,通常意义上不会有资源泄漏。

仍有一个可能存在问题的情况。假设您在释放某些资源时执行某些逻辑,即在C ++中或在Java中Closeable.close的实现中放入析构函数。例如,您在内存中有一个缓存,可以延迟写入带有批处理的文件。通常,您在onDestroy中刷新内存缓存,一切正常。但是当Android强制终止进程时,onDestroy可能没有被调用,并且您的刷新逻辑没有被执行,因此您可能会丢失一些数据和/或在您的持久存储中具有无效状态。因此,如果您有类似的内容,则应通过在更可靠的位置执行此类逻辑来确保一致性:onPauseonStop