170

我正在开发android应用程序一段时间,并关注了很多关于活动生命周期和应用程序生命周期的帖子。

我知道Activity.finish()在某处调用方法Activity.onDestroy(),并且还从堆栈中删除了活动,我猜它以某种方式指向操作系统和垃圾收集器,他可以“做他的伎俩”并在找到合适的时候释放内存所以....

我来到这个帖子 - 退出应用程序是否令人不悦?并阅读马克墨菲的答案。

这让我对这个方法到底做了什么感到有点困惑finish()

有没有机会我会打电话finish()onDestroy()不会被打电话?

4

13 回答 13

188

当调用finish()一个活动时,该方法onDestroy()被执行。此方法可以执行以下操作:

  1. 关闭活动正在管理的任何对话框。
  2. 关闭活动正在管理的所有游标。
  3. 关闭任何打开的搜索对话框

另外,onDestroy()不是析构函数。它实际上并没有破坏对象。它只是一种基于某种状态调用的方法。因此,在超类运行并返回之后,您的实例仍然存在并且非常好* onDestroy()。Android 保留进程以防用户想要重新启动应用程序,这使得启动阶段更快。该进程将不会做任何事情,如果需要回收内存,该进程将被杀死

于 2012-06-02T14:14:09.987 回答
90

我在@K_Anas 上的 2 美分回答。我对 finish() 方法进行了简单的测试。列出Activity生命周期中重要的回调方法

  1. 在 onCreate() 中调用 finish():onCreate() -> onDestroy()
  2. 在 onStart() 中调用 finish() :onCreate() -> onStart() -> onStop() -> onDestroy()
  3. 在 onResume() 中调用 finish():onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()

我的意思是,在执行 finish() 时,会调用这些方法的对应部分以及介于两者之间的任何方法。

例如:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
于 2015-09-10T17:35:48.077 回答
44

另请注意,如果您在意图之后调用 finish(),您将无法使用“返回”按钮返回上一个活动

startActivity(intent);
finish();
于 2017-04-12T08:11:26.670 回答
13

onDestroy()用于最终清理 - 释放您自己可以使用的资源、关闭打开的连接、阅读器、作者等。如果你不覆盖它,系统就会做它必须做的事情。

另一方面,finish()只是让系统知道程序员想要Activity完成当前的工作。因此,它onDestroy()在那之后调用。

需要注意的一点:

没有必要调用 tofinish()触发调用onDestroy(). 不。我们知道,如果android系统觉得有当前需要的资源需要Activity被释放,它就可以自由地杀死活动。

于 2012-06-01T09:17:56.270 回答
10

除了上面的@rommex 答案之外,我还注意到finish()确实会排队销毁 Activity 并且它取决于 Activity 优先级。

如果我finish()在 之后打电话onPause(),我看到了onStop(),并onDestroy()立即打电话。

如果我finish()在之后打电话onStop(),我要onDestroy()等到 5 分钟后才能看到。

根据我的观察,finish 似乎已排队,当我查看它时adb shell dumpsys activity activities它被设置为finishing=true,但由于它不再位于前台,因此它没有优先销毁。

总之,onDestroy()永远不能保证被调用,但即使在被调用的情况下,它也可能被延迟。

于 2018-08-31T04:25:27.653 回答
9

Finish() 方法将销毁当前活动。如果您不希望在用户按下后退按钮时一次又一次地加载此活动,则可以使用此方法。基本上它会从当前堆栈中清除活动。

于 2013-08-12T11:13:33.193 回答
6

各种答案和注释声称finish()可以跳过onPause()和onStop()并直接执行onDestroy()。公平地说,有关此的 Android 文档(http://developer.android.com/reference/android/app/Activity.html)指出“活动正在完成或被系统破坏”,这非常模棱两可,但可能暗示finish() 可以跳转到 onDestroy()。

finish() 上的 JavaDoc 也同样令人失望(http://developer.android.com/reference/android/app/Activity.html#finish()),实际上并没有注意到调用了哪些方法来响应完成()。

所以我在下面写了这个迷你应用程序,它在进入时记录每个状态。它包括一个调用 finish() 的按钮——因此您可以查看哪些方法被触发的日志。这个实验表明,finish()确实也调用了 onPause() 和 onStop()。这是我得到的输出:

2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onCreate
2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onStart
2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onResume
2170-2170/? D/LIFECYCLE_DEMO﹕ User just clicked button to initiate finish() 
2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onPause
2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onStop 
2170-2170/? D/LIFECYCLE_DEMO﹕ INSIDE: onDestroy

package com.mvvg.apps.lifecycle;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

public class AndroidLifecycle extends Activity {

    private static final String TAG = "LIFECYCLE_DEMO";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "INSIDE: onCreate");
        setContentView(R.layout.activity_main);
        LinearLayout layout = (LinearLayout) findViewById(R.id.myId);
        Button button = new Button(this);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View view) {
                Toast.makeText(AndroidLifecycle.this, "Initiating finish()",
                        Toast.LENGTH_SHORT).show();
                Log.d(TAG, "User just clicked button to initiate finish()");
                finish();
            }

        });

        layout.addView(button);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "INSIDE: onStart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "INSIDE: onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "INSIDE: onDestroy");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "INSIDE: onPause");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "INSIDE: onResume");
    }

}
于 2015-05-11T12:19:21.837 回答
4

@user3282164 根据Activity生命周期,它应该在调用时经过onPause()-> onStop()-> 。onDestroy()finish()

该图没有显示onDestroy()由系统引起的从 [Activity Running] 到 [ ] 的任何直线路径。

onStop()文档说“请注意,在调用 onPause() 方法后系统没有足够内存来保持活动进程运行的低内存情况下,可能永远不会调用此方法。 ”

于 2015-03-03T05:02:45.747 回答
3

我的研究表明,该finish()方法实际上在队列中放置了一些销毁操作,但 Activity 并没有立即销毁。破坏是预定的。

例如,如果您放置finish()onActivityResult()回调中,而 whileonResume()还没有运行,那么 first将被执行,然后onResume()才被调用。onStop()onDestroy()

注意:onDestroy()可能根本不会被调用,如文档中所述。

于 2016-02-25T06:51:32.077 回答
3

正如@prakash 所说,在 onCreate() 中调用 finish 不会直接调用 onDestroy() 。在您将控制权交还给 Android 之前,该finish()操作甚至不会开始。

在onCreate()中调用 finish( ) :onCreate() -> onStart() -> onResume()。如果用户退出应用程序将调用-> onPause() -> onStop() -> onDestroy()

在onStart()中调用 finish( ) :onCreate() -> onStart() -> onStop() -> onDestroy()

在onResume()中调用 finish( ) :onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()

如需进一步参考,请查看此oncreate Continuous after finish & about finish()

于 2017-04-06T10:23:04.323 回答
1

到目前为止,romnex 似乎给出了唯一正确的答案:“onDestroy() 可能根本不会被调用”。即使在实践中,几乎在所有情况下都可以,但不能保证:finish() 上的文档只承诺将活动的结果传播回调用者,但仅此而已。此外,生命周期文档阐明,一旦 onStop() 完成(甚至在旧设备上更早),操作系统就可以终止该活动,尽管这不太可能,因此在简单测试中很少观察到,这可能意味着该活动可能在执行 onDestroy() 时甚至之前被杀死。

因此,如果您想确保在调用 finish() 时完成了某些工作,则不能将其放入 onDestroy() 中,而是需要在调用 finish() 之前,在实际调用它之前在同一个地方进行。

于 2016-04-09T00:59:46.333 回答
1

Roomex 说的对!

发生在我身上的是我正在开发一个需要我使用蓝牙监听器类的应用程序。主页上的一个 Fragment 调用了一个也在使用 BluetoothListner 类的活动。我使用startActivityForResult()方法来获得确认。问题是在尝试侦听蓝牙端口时获得片段的确认后,活动通道仍然处于活动状态。即使我专门关闭了它的onDestroy()方法。我花了好几天,但不知道如何停下来。

我想如果我不使用startAcivityForResult()并且只使用startActivity()有和没有调用的finish()方法,这可能会解决这个问题。当然,如果我确实在片段中调用完成(),那么从活动中将不得不使用导航视图调用 MainActivity 并指向片段。这样,它可能会创建一个全新的 MainActivity 实例。或者在调用 Activity 时不使用finish() , onDestroy()方法将为 Activity 调用,并且片段的onResume()方法将在我们返回时被调用。

于 2021-03-11T09:43:11.367 回答
-5

finish() 只是返回到 android 中的上一个活动,或者您可以说它在应用程序中退了一步

于 2014-03-29T11:49:00.587 回答