Was genau macht die Activity.finish () -Methode?

155

Ich entwickle Android-Anwendungen für eine Weile und verfolge viele Beiträge über den Aktivitätslebenszyklus und den Lebenszyklus der Anwendung.

Ich weiß, dass Activity.finish()Methodenaufrufe irgendwo im Weg Activity.onDestroy()sind und auch die Aktivität vom Stapel entfernen, und ich denke, dass dies irgendwie auf das Betriebssystem und den Garbage Collector hinweist, dass er "seinen Trick machen" und den Speicher freigeben kann, wenn es eine gute Zeit ist so....

Ich bin zu diesem Beitrag gekommen - Wird das Beenden einer Bewerbung verpönt? und lesen Sie Mark Murphys Antwort.

Es hat mich ein bisschen verwirrt darüber, was genau die finish()Methode tatsächlich tut.

Gibt es eine Chance, dass ich anrufe finish()und onDestroy()nicht angerufen werde?

Tal Kanel
quelle

Antworten:

171

Beim Aufrufen finish()einer Aktivität wird die Methode onDestroy()ausgeführt. Diese Methode kann Dinge tun wie:

  1. Schließen Sie alle Dialoge, die von der Aktivität verwaltet wurden.
  2. Schließen Sie alle Cursor, die von der Aktivität verwaltet wurden.
  3. Schließen Sie alle geöffneten Suchdialoge

Ebenfalls, onDestroy() ist kein Destruktor. Es zerstört das Objekt nicht wirklich. Es ist nur eine Methode, die basierend auf einem bestimmten Zustand aufgerufen wird. Ihre Instanz ist also noch am Leben und sehr gut *, nachdem die Oberklasse ausgeführt onDestroy()und zurückgegeben wurde. Android behält die Prozesse bei, falls der Benutzer die App neu starten möchte. Dies beschleunigt die Startphase. Der Prozess wird nichts tun und wenn Speicher zurückgefordert werden muss, wird der Prozess abgebrochen

K_Anas
quelle
5
Also beendet die Methode finish () nur den Aufruf von onDestroy () und das wars?
Tal Kanel
9
Ja, wenn Sie zur Aktivität zurückkehren, wird onCreate () aufgerufen.
Luis Pena
9
Ruft finish () auch onPause () und onStop () auf?
sr09
36
Ich habe erneut getestet und festgestellt, dass onPause (), onStop () und onDestroy () alle nach dem Aufruf von finish () der Reihe nach aufgerufen werden.
Sam003
5
@Laurent onPause () und onStop () werden nicht immer aufgerufen. Siehe meine Beobachtung in der folgenden Antwort
Prakash
77

Meine 2 Cent auf @K_Anas antworten. Ich habe einen einfachen Test mit der Methode finish () durchgeführt. Auflistung wichtiger Rückrufmethoden im Aktivitätslebenszyklus

  1. Aufruf von finish () in onCreate (): onCreate () -> onDestroy ()
  2. Aufruf von finish () in onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Aufruf von finish () in onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Was ich damit sagen will ist, dass Gegenstücke der Methoden zusammen mit allen dazwischen liegenden Methoden aufgerufen werden, wenn finish () ausgeführt wird.

z.B:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
Prakash
quelle
Was ist, wenn Sie Finish in onPause aufrufen? es wird onStop> onDestroy aufrufen?
rmpt
Diese Tabelle ist wirklich nützlich und beschreibend (Sie müssen ein wenig nach unten scrollen) developer.android.com/reference/android/app/…
winklerrr
Ich selbst habe überprüft, ob diese Antwort richtig ist.
Sreekanth Karumanaghat
33

Beachten Sie auch, dass Sie, wenn Sie nach einer Absicht finish () aufrufen, nicht mit der Schaltfläche "Zurück" zur vorherigen Aktivität zurückkehren können

startActivity(intent);
finish();
Dan trägt Prada
quelle
Dies ist genau die Information, die ich brauchte, da ich eine Aktivität habe, die nur eine Verbindung zu Google Drive herstellt. Dann werden die Überprüfungen durchgeführt und es wird zur Hauptaktivität (oder zur Aktivität "Einstellungen" übergegangen, wenn ein Fehler auftritt), sodass der Benutzer dies nicht tun sollte Ich kann nicht zurück.
Francesco Marchetti-Stasi
1
@Francesco Marchetti-Stasi In Ihrem Fall ist es besser, onBackPressed () zu überschreiben und nicht super.onBackPressed () darin aufzurufen, wenn der Benutzer nicht zurückkehren sollte.
Paul
13

onDestroy()ist für die endgültige Bereinigung gedacht - um Ressourcen freizugeben, die Sie selbst nutzen können, um offene Verbindungen, Leser, Autoren usw. zu schließen. Wenn Sie es nicht überschreiben, tut das System, was es muss.

Auf der anderen Seite wird finish()das System nur darüber informiert, dass der Programmierer möchte, dass der Strom Activitybeendet wird. Und daher ruft es aufonDestroy() danach auf.

Etwas zu beachten:

Es ist nicht erforderlich, dass nur ein Anruf einen Anruf finish()auslöst onDestroy(). Nein. Wie wir wissen, kann das Android-System Aktivitäten beenden, wenn es den Eindruck hat, dass der Strom Ressourcen Activitybenötigt, die freigegeben werden müssen.

Kazekage Gaara
quelle
1
Sie haben geschrieben, dass finish () das System darüber informiert, dass die Aktivität beendet werden muss. Es ist also so, als würde man sagen "do x = sag dem System, dass es x machen soll". Sekunden-Sache: Aus Ihrer Antwort geht hervor, dass es eine Möglichkeit gibt, wie ich finish () aufrufe, und das System entscheidet, onDestroy () nicht aufzurufen? ist es möglich?
Tal Kanel
Du hast den ersten Teil richtig verstanden. Das Anrufen finish()weist das System an, das zu beenden Activity. Der "x" -Teil in Ihrer do-Anweisung lautet "das beenden (zerstören) Activity". Der zweite Teil ist falsch. Eigentlich habe ich dort ein Wort verpasst. Ich habe die Antwort bearbeitet. onDestroy()wird nicht nur ausgelöst durch finish(), das System kann es auch selbst aufrufen.
Kazekage Gaara
1
Ich habe gerade Ihren Zusatz zur Antwort gelesen. Im Moment habe ich die Antwort hochgestimmt, weil ich Ihre Erklärung interessant fand, aber ich würde gerne sehen, ob andere etwas anderes dazu sagen würden, bevor ich sie als "Antwort" markiere. Danke fürs
Erste
Nach finish () werden also alle Variablen in dieser Aktivität zerstört, oder? Wenn ich noch einmal auf diese Aktivität zurückkomme, werden sie erneut deklariert oder initialisiert, oder?
Sibbs Gambling
3
Hinweis: Wenn das System den Prozess abbricht, wird onDestroy möglicherweise nicht aufgerufen. developer.android.com/reference/android/app/…
Kevin Lee
9

Die Methode Finish () zerstört die aktuelle Aktivität. Sie können diese Methode in Fällen verwenden, in denen diese Aktivität nicht immer wieder geladen werden soll, wenn der Benutzer die Zurück-Taste drückt. Grundsätzlich wird die Aktivität aus dem aktuellen Stapel gelöscht.

Udit Kapahi
quelle
8

Zusätzlich zu der obigen Antwort von @rommex habe ich auch festgestellt, dass finish()die Zerstörung der Aktivität in die Warteschlange gestellt wird und dass dies von der Priorität der Aktivität abhängt.

Wenn ich rufe finish()nach onPause(), sehe ich onStop(), und onDestroy()sofort aufgerufen.

Wenn ich rufe finish()nach onStop(), sehe ich nicht , onDestroy()erst 5 Minuten später.

Nach meiner Beobachtung sieht es so aus, als ob das Ziel in der Warteschlange steht und als ich mir das anschaute, auf das adb shell dumpsys activity activitieses eingestellt war finishing=true, aber da es nicht mehr im Vordergrund steht, wurde es nicht für die Zerstörung priorisiert.

Zusammenfassend lässt onDestroy()sich sagen, dass ein Anruf niemals garantiert wird, aber selbst wenn er aufgerufen wird, kann er sich verzögern.

Brandon Lim
quelle
5

Verschiedene Antworten und Notizen behaupten, dass finish () onPause () und onStop () überspringen und onDestroy () direkt ausführen kann. Um fair zu sein, wird in der Android-Dokumentation dazu ( http://developer.android.com/reference/android/app/Activity.html ) darauf hingewiesen, dass die Aktivität beendet oder vom System zerstört wird. Dies ist ziemlich zweideutig, könnte aber darauf hindeuten finish () kann zu onDestroy () springen.

Das JavaDoc on finish () ist ähnlich enttäuschend ( http://developer.android.com/reference/android/app/Activity.html#finish () ) und merkt nicht an, welche Methoden als Reaktion auf das Finish aufgerufen werden ().

Also habe ich diese Mini-App geschrieben, die jeden Status bei der Eingabe protokolliert. Es enthält eine Schaltfläche, die finish () aufruft, sodass Sie die Protokolle sehen können, welche Methoden ausgelöst werden. Dieses Experiment würde darauf hinweisen , dass finish () tatsächlich auch onPause () und onStop () aufruft. Hier ist die Ausgabe, die ich bekomme:

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");
    }

}
CoderOfTheNight
quelle
3

@ user3282164 Entsprechend dem Aktivitätslebenszyklus sollte er beim Aufruf onPause()-> onStop()-> durchlaufen .onDestroy()finish()

Das Diagramm zeigt keinen geraden Pfad von [Aktivität ausgeführt] zu [ onDestroy()], der vom System verursacht wird.

onStop () doc sagt: " Beachten Sie, dass diese Methode in Situationen mit wenig Arbeitsspeicher, in denen das System nicht über genügend Arbeitsspeicher verfügt, um den Prozess Ihrer Aktivität nach dem Aufruf der Methode onPause () am Laufen zu halten , möglicherweise nie aufgerufen wird. "

Meryan
quelle
NICHT GENAU siehe: stackoverflow.com/questions/12655898/…
ceph3us
2

Meine Studie zeigt, dass die finish()Methode tatsächlich einige Zerstörungsoperationen in die Warteschlange stellt, die Aktivität jedoch nicht sofort zerstört wird. Die Zerstörung ist jedoch geplant.

Zum Beispiel, wenn Sie Platz finish()in onActivityResult()Rückruf, während onResume()noch laufen müssen dann erst onResume()wird ausgeführt, und danach nur werden onStop()und onDestroy()aufgerufen werden .

HINWEIS: onDestroy()darf überhaupt nicht aufgerufen werden, wie in der Dokumentation angegeben .

rommex
quelle
2

Wenn Sie finish in onCreate () aufrufen, wird onDestroy () nicht direkt aufgerufen, wie @prakash sagte. Der finish()Vorgang beginnt erst, wenn Sie die Kontrolle an Android zurückgeben.

Aufruf von finish () in onCreate () : onCreate () -> onStart () -> onResume () . Wenn der Benutzer beendet wird, ruft die App -> onPause () -> onStop () -> onDestroy () auf.

Aufruf von finish () in onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Aufruf von finish () in onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Weitere Referenzüberprüfungen finden Sie in dieser Datei, die nach Abschluss und nach Abschluss () fortlaufend erstellt wird.

anand krish
quelle
0

Es scheint, dass die einzig richtige Antwort hier bisher von romnex gegeben wurde: "onDestroy () darf überhaupt nicht aufgerufen werden". Obwohl es in der Praxis in fast allen Fällen keine Garantie gibt: Die Dokumentation zu finish () verspricht nur, dass das Ergebnis der Aktivität an den Aufrufer zurückgesendet wird, nicht mehr. Darüber hinaus wird in der Lebenszyklusdokumentation klargestellt, dass die Aktivität vom Betriebssystem beendet werden kann, sobald onStop () beendet ist (oder sogar früher auf älteren Geräten). Dies ist zwar unwahrscheinlich und daher in einem einfachen Test selten zu beobachten, kann jedoch bedeuten, dass die Aktivität ausgeführt wird kann getötet werden, während oder sogar bevor onDestroy () ausgeführt wird.

Wenn Sie also sicherstellen möchten, dass beim Aufrufen von finish () einige Arbeiten ausgeführt werden, können Sie diese nicht in onDestroy () einfügen, sondern müssen sie an derselben Stelle ausführen, an der Sie finish () aufrufen, bevor Sie sie tatsächlich aufrufen.

urps
quelle
-4

finish () sendet einfach zurück zur vorherigen Aktivität in Android, oder Sie können sagen, dass es in der Anwendung einen Schritt zurück geht

kapil
quelle