Activity.finish()メソッドは正確に何をしているのですか?


156

私はしばらくAndroidアプリケーションを開発しており、アクティビティのライフサイクルとアプリケーションのライフサイクルに関する多くの投稿をフォローしています。

Activity.finish()メソッドがのどこかで呼び出され、Activity.onDestroy()スタックからアクティビティが削除されることも知っています。オペレーティングシステムとガベージコレクターが「トリックを実行」してメモリを解放できるのは、それが良い時間だとわかったときだと思います。そう....

私はこの投稿に来ました- アプリケーションを終了することは眉をひそめていますか?マーク・マーフィーの答えを読んでください。

そのfinish()方法が実際に何をしているのかについて少し混乱しました。

電話をかけfinish()onDestroy()もらえない可能性はありますか?


回答:


171

finish()アクティビティを呼び出すと、メソッドonDestroy()が実行されます。このメソッドは次のようなことを実行できます。

  1. アクティビティが管理していたダイアログをすべて閉じます。
  2. アクティビティが管理していたカーソルをすべて閉じます。
  3. 開いている検索ダイアログをすべて閉じます

また、onDestroy()デストラクタではありません。実際にはオブジェクトを破壊しません。これは、特定の状態に基づいて呼び出される単なるメソッドです。そのため、スーパークラスがonDestroy()実行されて戻った後も、インスタンスはまだ生きていて非常に良好です* 。Androidは、ユーザーがアプリを再起動したい場合に備えてプロセスを保持します。これにより、起動フェーズが速くなります。プロセスは何も実行せず、メモリを解放する必要がある場合、プロセスは強制終了されます


5
それで、finish()メソッドはonDestroy()の呼び出しのみをトリガーし、それだけですか?
Tal Kanel

9
はい、アクティビティに戻るとonCreate()が呼び出されます。
Luis Pena 14

9
finish()はonPause()とonStop()も呼び出しますか?
sr09 2014

36
もう一度テストしましたが、finish()を呼び出した後、onPause()、onStop()、onDestroy()が順番に呼び出されることがわかりました。
Sam003

5
@Laurent onPause()およびonStop()は常に呼び出されるわけではありません。以下の答えで私の観察を参照してください
Prakash

77

@K_Anasの私の2セントの答え。finish()メソッドで簡単なテストを実行しました。アクティビティのライフサイクルで重要なコールバックメソッドをリストしました

  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()

onPause内でfinishを呼び出すとどうなりますか?onStop> onDestroy?
rmpt 2016年

そのテーブルには、(あなたが少し下にスクロールする必要が)本当に具体的でわかりやすいですdeveloper.android.com/reference/android/app/...
winklerrr

私自身、この答えが正しいことを確認しました。
Sreekanth Karumanaghat

33

また、インテントの後でfinish()を呼び出すと、「戻る」ボタンで前のアクティビティに戻ることができないことに注意してください。

startActivity(intent);
finish();

これはまさに私が必要とする情報です。私はgoogleドライブに接続するだけのアクティビティを持っているので、それはチェックを行い、メインアクティビティ(またはエラーがある場合は設定アクティビティ)に移動するので、ユーザーは戻ることができません。
Francesco Marchetti-Stasi

1
@Francesco Marchetti-Stasiあなたの場合、ユーザーが戻る必要がない場合は、onBackPressed()をオーバーライドし、その中でsuper.onBackPressed()を呼び出さない方がよいでしょう。
ポール

13

onDestroy()最終的なクリーンアップのためのものです-自分でできるリソースを解放し、開いている接続、リーダー、ライターなどを閉じます。オーバーライドしない場合、システムは必要な処理を実行します。

一方、finish()プログラマーに電流のActivity終了を望んでいることをシステムに通知するだけです。したがって、その後に呼び出されonDestroy()ます。

注意すべき点:

への呼び出しのみがへの呼び出しをfinish()トリガーする必要はありませんonDestroy()。いいえ。ご存知のように、Androidシステムは、解放する必要のある電流Activityが必要とするリソースがあると感じた場合、活動を強制終了できます。


1
finish()を作成して、アクティビティを終了する必要があることをシステムに通知しました。つまり、「do x =システムにxを実行するように指示する」と言うようなものです。秒のこと:あなたの答えから、finish()を呼び出す方法があるように聞こえ、システムはonDestroy()を呼び出さないことを決定しますか?出来ますか?
Tal Kanel

あなたは最初の部分を正しく理解しました。呼び出しfinish()は、システムにを終了するように指示していますActivity。doステートメントの「x」の部分は、「を終了(破棄)することActivity」です。2番目の部分は間違っています。実は、一言も聞き逃してしまいました。回答を編集しました。onDestroy()はによってトリガーされるだけでなくfinish()、システム自身で呼び出すこともできます。
風影我ら

1
答えへの追加を読んだところです。今のところ、私はあなたの説明が興味深いと思ったので、回答に賛成票を投じました。今のところありがとう:)
Tal Kanel

それで、finish()の後、このアクティビティのすべての変数は破棄されますよね?もう一度このアクティビティに戻ると、再宣言または初期化されますよね?
Sibbsギャンブル2013

3
注:システムがプロセスを強制終了すると、onDestroyが呼び出されない場合があります。 developer.android.com/reference/android/app/...
ケビン・リー

9

Finish()メソッドは現在のアクティビティを破棄します。このメソッドは、ユーザーが戻るボタンを押したときにこのアクティビティを何度もロードしたくない場合に使用できます。基本的に、.currentスタックからアクティビティをクリアします。


8

上記の@rommexの回答に加えてfinish()、アクティビティの破棄がキューに入れられ、アクティビティの優先度に依存することにも気付きました。

finish()後に電話するとonPause()、が表示されonStop()onDestroy()すぐに電話がかかりました。

finish()後に電話した場合onStop()onDestroy()5分後まで表示されません。

私の観察では、仕上げはキューに入れられているように見え、私がadb shell dumpsys activity activitiesそれを見ると、それはに設定されてfinishing=trueいましたが、フォアグラウンドではなくなったため、破棄の優先順位が付けられていません。

要約onDestroy()すると、呼び出しが保証されることは決してありませんが、呼び出された場合でも、遅延する可能性があります。


5

さまざまな回答とメモが、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()を呼び出すボタンが含まれているため、どのメソッドが起動されたかのログを確認できます。この実験は、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");
    }

}

3

@ user3282164 アクティビティのライフサイクルによると、呼び出し時にonPause()-> onStop()-> onDestroy()を通過する必要がありfinish()ます。

この図にはonDestroy()、システムが原因で発生する[Activity Running]から[ ] への直線経路は示されていません。

onStop() docは、「onPause()メソッドが呼び出された後、アクティビティのプロセスを実行し続けるのに十分なメモリがシステムにないメモリ不足の状況では、このメソッドは決して呼び出されないことに注意してください。



2

私の調査によると、finish()メソッドは実際にいくつかの破棄操作をキューに入れていますが、アクティビティはすぐには破棄されません。破壊は予定されています。

あなたが置いた場合たとえば、finish()中にonActivityResult()いる間、コールバックonResume()を実行するためには至っていない、最初onResume()で唯一その後、実行されますonStop()onDestroy()呼ばれています。

注:ドキュメントにonDestroy()記載されているように、はまったく呼び出されない場合があります


2

onCreate()でfinishを呼び出しても、@ prakashが言ったようにonDestroy()を直接呼び出すことはありません。finish()Androidに制御を戻すまで、操作は開始されません。

onCreate()でfinish()を呼び出す:onCreate()-> onStart()-> onResume()。ユーザーが終了すると、アプリは-> onPause()-> onStop()-> onDestroy()を呼び出します

onStart()でfinish()を呼び出す:onCreate()-> onStart()-> onStop()-> onDestroy()

onResume()でfinish()を呼び出す:onCreate()-> onStart()-> onResume()-> onPause()-> onStop()-> onDestroy()

詳細なリファレンスについては、このoncreateの終了後、およびfinish()についての継続を参照してください。


0

これまでのところ、唯一正しい答えはromnexによって提供されているようです:「onDestroy()はまったく呼び出されない可能性があります」。実際には、ほとんどすべてのケースで保証されますが、保証はありません。finish()のドキュメントでは、アクティビティの結果が呼び出し元に伝播されることのみが約束されていますが、それ以上のものはありません。さらに、ライフサイクルのドキュメントでは、onStop()が終了するとすぐに(または古いデバイスではさらに早く)、OSがアクティビティを強制終了できることが明記されています。 onDestroy()の実行中または実行前に強制終了される可能性があります。

したがって、finish()を呼び出すときに何らかの処理が行われるようにしたい場合は、onDestroy()に置くことはできませんが、finish()を呼び出すのと同じ場所で、実際に呼び出す前に行う必要があります。


-4

finish()は、Androidの前のアクティビティに戻るだけです。または、アプリケーションで1ステップ戻っていると言えるかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.