Activity.finish()方法到底在做什么?

时间:2012-06-01 09:13:01

标签: android activity-lifecycle ondestroy application-lifecycle

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

我知道Activity.finish()方法调用Activity.onDestroy()的方式,并从堆栈中删除活动,我想它以某种方式指向操作系统和垃圾收集器,他可以“做他的伎俩“当它发现这是一个很好的时间时,释放记忆......

我来到这个帖子 - Is quitting an application frowned upon?并阅读Mark Murphy的回答。

这让我对finish()方法实际上做了什么感到困惑。

我是否有机会致电finish()并且onDestroy()将不会被召唤?

12 个答案:

答案 0 :(得分:150)

在活动上调用 finish() 时,会执行 onDestroy() 方法。此方法可以执行以下操作:

  1. 关闭活动管理的所有对话框。
  2. 关闭活动管理的所有游标。
  3. 关闭所有打开的搜索对话框
  4. 此外, onDestroy() 不是析构函数。它实际上并没有破坏对象。它只是一种基于某种状态调用的方法。因此,在超类的onDestroy()运行并返回之后,您的实例仍然存活且非常好.Android会保留进程,以防用户想要重新启动应用程序,这会使启动阶段更快。该过程将不会执行任何操作,如果需要回收内存,则该过程将被终止

答案 1 :(得分:19)

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

$(document).ready(function()
            {
                'use strict';
                $.ajax
                ({
                    method: "get",
                    url: "requestOffer.php"
                })
                .done(function(data)
                {
                    var offers = JSON.parse(data);

                    // now we have the data attach the autocomplete
                    $('#EOffers').autocomplete
                    ({
                        minLength:3,
                        source: offers,
                        select: function(event, ui) 
                        {
                            $('#chosenEvent').text(ui.item.label);
                            $('#chosenEvent').text(ui.item.vanue);
                        }
                    });
                });
            });

答案 2 :(得分:12)

onDestroy()用于最终清理 - 释放您可以自己拥有的资源,关闭开放式连接,读者,编写者等。如果你不覆盖它,系统会做它所拥有的。

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

需要注意的事项:

finish()的调用不一定会触发对onDestroy()的调用。不。如我们所知,如果感觉需要释放当前Activity所需的资源,则android系统可以自由地杀死活动。

答案 3 :(得分:6)

Finish()方法将破坏当前活动。 如果您不想在用户按下后退按钮时反复加载此活动,则可以使用此方法。 基本上它会清除当前堆栈中的活动。

答案 4 :(得分:4)

各种答案和说明声称finish()可以跳过onPause()和onStop()并直接执行onDestroy()。公平地说,关于此(http://developer.android.com/reference/android/app/Activity.html)注释"活动的Android文档正在完成或被系统销毁#34;这是非常模糊但可能暗示finish()可以跳转到onDestroy()。

finish()上的JavaDoc同样令人失望(http://developer.android.com/reference/android/app/Activity.html#finish())并且实际上并没有注意响应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");
    }

}

答案 5 :(得分:3)

@ user3282164根据Activity生命周期,它应该通过onPause() - > onStop() - >致电onDestroy()finish()

该图表未显示由系统引起的[活动运行]到[onDestroy()]的任何直接路径。

onStop() doc说 " 请注意,在内存不足的情况下,此方法可能会从不被调用,在这种情况下,系统没有足够的内存来保持您的活动进程在其onPause()之后运行方法被称为。"

答案 6 :(得分:2)

我的研究表明,finish()方法实际上在队列中放置了一些销毁操作,但活动不会立即销毁。但是计划进行破坏。

例如,如果您在finish()回调中放置onActivityResult(),而onResume()尚未运行,则会先执行onResume(),然后才会执行onStop() onDestroy() 1}}和onDestroy()被调用。

注意:根据documentation的说明,可能根本不会调用require_once 'app/code/local/Ced/CsMarketplace/controllers/AccountController.php'; class Core_Ced_CsMarketplace_AccountController extends Ced_CsMarketplace_Controller_AbstractController { /** * Create customer account action */ public function createPostAction() { //my custom code } }

答案 7 :(得分:2)

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

如果我在finish()之后呼叫onPause(),则会看到onStop(),并立即呼叫onDestroy()

如果我在finish()之后致电onStop(),则直到5分钟后我才看到onDestroy()

从我的观察来看,似乎完成已排队,当我查看adb shell dumpsys activity activities时将其设置为finishing=true,但是由于它不再位于前台,因此没有优先级破坏。

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

答案 8 :(得分:1)

在onCreate()中调用finish不会直接调用onDestroy(),因为@prakash说。在您将控制权返回给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()

答案 9 :(得分:0)

到目前为止,romnex似乎给出了唯一正确的答案:" onDestroy()可能根本不会被调用"。即使在实践中,几乎在所有情况下都是如此,但不能保证:documentation on finish()只承诺活动的结果传播回调用者,但仅此而已。此外,lifecycle documentation阐明了一旦onStop()完成(或者甚至更早在旧设备上),操作系统就可以对活动进行操作,这虽然不太可能,因此在一个简单的测试中很难观察到,但这可能意味着在执行onDestroy()之前或甚至在执行onDestroy()之前,活动可能会被杀死。

因此,如果你想确保在调用finish()时完成一些工作,你不能把它放在onDestroy()中,但是需要在你调用finish()的地方做,就在实际调用之前它

答案 10 :(得分:0)

Roomex 说得对!

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

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

答案 11 :(得分:-6)

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