关于android:在onPause而不是onDestroy中释放资源

Release resources in onPause instead of onDestroy

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

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

Note the"Killable" column in the above table -- for those methods
that are marked as being killable, after that method returns the
process hosting the activity may be killed by the system at any time
without another line of its code being executed

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

    另一句话说:

    For those methods that are not marked as being killable, the
    activity's process will not be killed by the system starting from the
    time the method is called and continuing after it returns.

    其次是

    Thus an activity is in the killable state, for example, between after
    onPause() to the start of onResume().

  • 但这与上述内容不符,除非这只对应于PRE蜂窝。对于POST蜂窝,情况并非如此,对吧?所以基本上,onPause和onStop都可以保证被调用。

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

  • 但是,这个场景(即onDestroy没有被调用)是否会发生在进程被android本身杀死的时候?是否有任何其他方案导致不调用onDestroy,从而泄漏资源。

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

  • 请提供详细资料,说明这些陈述(1)(2)(3)(4)(5)是否正确。


    首先,让我们了解您引用的文档会发生什么。

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

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

    输出的相关部分:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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 at any time 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 Process Lifecycle
    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 <wyn>onPause()</wyn> to the start of
    9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800  392)  * <wyn>onResume()</wyn>.
    </p>

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

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

    对你的问题:

    1)在后Honeycomb版本的Android上,保证onResume()onStop()被调用(如Dianne Hackborn在Activity的javadoc中所述)。

    2)在预蜂窝之前,只保证onPause()被调用(如早期版本的Activity的javadoc所述)

    3,4,5)只有在托管整个应用程序的进程被终止时才会调用onDestroy()。当进程被终止时,分配给它的所有资源都被释放,因此在这种情况下不存在内存泄漏的风险。

    重要说明:由于释放onDestroy()中的资源不会导致内存泄漏,因此将所有"释放"代码放在那里似乎是个好主意。但是,它很少是最佳方法。为什么?参见下文。

    Activity进入后台时,它会停止,但不会被破坏(通常)。 Activity可以在相当长的时间内保持此"停止"状态,并且如果用户返回应用程序将再次启动。如果您在onDestroy()中释放资源(默认情况下,当Activity转到后台时),Activity将在处于停止状态时保留这些资源,从而导致应用程序消耗更多资源背景状态。

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

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

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

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


    我认为瓦西里提供了一个很好的答案。仍有一个小而重要的点与那里有关

  • Is it true that when Android kills the process that the resources will be destroyed and no leak can occur (even when we did not explicitly released the resource?).
  • 答案取决于你究竟害怕什么。正如Vasily所指出的,Android(基于Linux)是一个现代安全的操作系统,它保证当进程被终止时,所有内存都将被释放,而且所有打开的文件,网络连接等也将被正确关闭。因此,通常意义上不会有资源泄漏。

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