Que fait exactement la méthode Activity.finish ()?

156

Je développe des applications Android depuis un moment et j'ai suivi de nombreux articles sur le cycle de vie des activités et le cycle de vie des applications.

Je sais que la Activity.finish()méthode appelle quelque part sur le chemin de Activity.onDestroy(), et supprime également l'activité de la pile, et je suppose que cela indique en quelque sorte le système d'exploitation et le ramasse-miettes qu'il peut "faire son tour" et libérer la mémoire quand il trouve le bon moment de le faire alors....

Je suis venu à ce poste - Est-ce que quitter une application est mal vu? et lisez la réponse de Mark Murphy.

Cela m'a rendu un peu confus sur ce que fait exactement la finish()méthode.

Y at - il une chance que je vais appeler finish()et onDestroy()ne sera pas appelé?

Tal Kanel
la source

Réponses:

171

Lors de l'appel finish()à une activité, la méthode onDestroy()est exécutée. Cette méthode peut faire des choses comme:

  1. Ignorez tous les dialogues gérés par l'activité.
  2. Fermez tous les curseurs gérés par l'activité.
  3. Fermez toute boîte de dialogue de recherche ouverte

Ce onDestroy()n'est pas non plus un destructeur. Cela ne détruit pas réellement l'objet. C'est juste une méthode qui est appelée en fonction d'un certain état. Ainsi, votre instance est toujours en vie et très bien * après les onDestroy()exécutions et les retours de la superclasse.Android maintient les processus au cas où l'utilisateur souhaite redémarrer l'application, ce qui accélère la phase de démarrage. Le processus ne fera rien et si la mémoire doit être récupérée, le processus sera tué

K_Anas
la source
5
donc la méthode finish () ne déclenchant qu'un appel à onDestroy () et c'est tout?
Tal Kanel
9
Oui, si vous revenez à l'activité, onCreate () sera appelé.
Luis Pena
9
Finish () appelle-t-il également onPause () et onStop ()?
sr09 du
36
J'ai testé à nouveau et j'ai trouvé que onPause (), onStop () et onDestroy () seront tous appelés dans l'ordre après avoir appelé finish ().
Sam003
5
@Laurent onPause () et onStop () ne sont pas toujours appelés. Voir mon observation dans la réponse ci-dessous
Prakash
77

Mes 2 cents sur la réponse @K_Anas. J'ai effectué un test simple sur la méthode finish (). Liste des méthodes de rappel importantes dans le cycle de vie de l'activité

  1. Appel de finish () dans onCreate (): onCreate () -> onDestroy ()
  2. Appel de finish () dans onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Appel de finish () dans onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Ce que je veux dire, c'est que les homologues des méthodes ainsi que toutes les méthodes intermédiaires sont appelées lorsque finish () est exécuté.

par exemple:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
Prakash
la source
et si vous appelez la fin à l'intérieur de onPause? il appellera onStop> onDestroy?
rmpt
Ce tableau est vraiment utile et descriptif (vous devez faire défiler un peu vers le bas) developer.android.com/reference/android/app
...
J'ai moi-même vérifié que cette réponse est correcte.
Sreekanth Karumanaghat
33

Notez également que si vous appelez finish () après un intent, vous ne pouvez pas revenir à l'activité précédente avec le bouton "retour"

startActivity(intent);
finish();
Dan porte Prada
la source
C'est exactement l'information dont j'avais besoin, puisque j'ai une activité qui se connecte uniquement à google drive, alors il fait ses vérifications et passe à l'activité principale (ou à l'activité Paramètres s'il y a une erreur), donc l'utilisateur ne devrait pas Je ne peux pas revenir en arrière.
Francesco Marchetti-Stasi
1
@Francesco Marchetti-Stasi Dans votre cas, il serait préférable de remplacer onBackPressed () et de ne pas appeler super.onBackPressed () si l'utilisateur ne doit pas revenir en arrière.
Paul
13

onDestroy()est destiné au nettoyage final - libérer des ressources que vous pouvez vous-même, fermer les connexions ouvertes, les lecteurs, les rédacteurs, etc. Si vous ne le remplacez pas, le système fait ce qu'il doit.

d'autre part, finish()informe simplement le système que le programmeur veut que le courant Activitysoit terminé. Et par conséquent, il appelleonDestroy() après cela.

Quelque chose à noter:

il n'est pas nécessaire que seul un appel à finish()déclenche un appel à onDestroy(). Non. Comme nous le savons, le système Android est libre de tuer des activités s'il estime que le courant a besoin de ressources Activityqui doivent être libérées.

Kazekage Gaara
la source
1
vous avez écrit que finish () informe le système que l'activité doit être terminée. donc c'est comme dire "faire x = dire au système de faire x". deuxième chose: à partir de votre réponse, il semble qu'il y ait un moyen d'appeler finish (), et le système décidera de ne pas appeler onDestroy ()? c'est possible?
Tal Kanel
Vous avez bien compris la première partie. L'appel finish()indique au système de terminer le Activity. la partie "x" de votre instruction do est "pour terminer (détruire) le Activity". La deuxième partie est fausse. En fait, j'ai raté un mot là-bas. J'ai édité la réponse. onDestroy()n'est pas seulement déclenché par finish(), le système peut également l'appeler seul.
Kazekage Gaara
1
Je viens de lire votre ajout à la réponse. pour l'instant, j'ai voté à la hausse parce que j'ai trouvé votre explication intéressante, mais j'aimerais voir si d'autres auraient autre chose à dire à ce sujet avant de la marquer comme "répondue". merci pour l'instant :)
Tal Kanel
Donc, après finish (), toutes les variables de cette activité seront détruites, non? Quand je reviendrai à cette activité, ils seront de nouveau déclarés ou initialisés, non?
Sibbs Gambling
3
Remarque: si le système arrête le processus, onDestroy peut ne pas être appelé. developer.android.com/reference/android/app/…
Kevin Lee
9

La méthode Finish () détruira l'activité en cours. Vous pouvez utiliser cette méthode dans les cas où vous ne souhaitez pas que cette activité se charge encore et encore lorsque l'utilisateur appuie sur le bouton Retour. Fondamentalement, il efface l'activité de la pile actuelle.

Udit Kapahi
la source
8

En plus de la réponse @rommex ci-dessus, j'ai également remarqué que finish()la destruction de l'activité est en file d'attente et que cela dépend de la priorité de l'activité.

Si j'appelle finish()après onPause(), je vois onStop(), et j'ai onDestroy()immédiatement appelé.

Si j'appelle finish()après onStop(), je ne vois onDestroy()que 5 minutes plus tard.

D'après mon observation, il semble que la finition soit en file d'attente et quand j'ai regardé le, adb shell dumpsys activity activitiesil était réglé sur finishing=true, mais comme il n'est plus au premier plan, il n'a pas été priorisé pour la destruction.

En résumé, il onDestroy()n'est jamais garanti d'être appelé, mais même dans le cas où il est appelé, il pourrait être retardé.

Brandon Lim
la source
5

Diverses réponses et notes affirment que finish () peut sauter onPause () et onStop () et exécuter directement onDestroy (). Pour être honnête, la documentation Android à ce sujet ( http://developer.android.com/reference/android/app/Activity.html ) indique que "l'activité se termine ou est détruite par le système", ce qui est assez ambigu mais pourrait suggérer que finish () peut sauter à onDestroy ().

Le JavaDoc sur finish () est également décevant ( http://developer.android.com/reference/android/app/Activity.html#finish () ) et ne note pas réellement quelle (s) méthode (s) sont appelées en réponse pour terminer ().

J'ai donc écrit cette mini-application ci-dessous qui enregistre chaque état lors de l'entrée. Il comprend un bouton qui appelle finish () - afin que vous puissiez voir les journaux des méthodes déclenchées. Cette expérience suggère que finish () appelle en effet également onPause () et onStop (). Voici le résultat que j'obtiens:

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
la source
3

@ user3282164 Selon le cycle de vie de l' activité , il doit passer onPause()-> onStop()-> onDestroy()lors de l'appelfinish() .

Le diagramme ne montre aucun chemin direct entre [Activité en cours d'exécution] et [ onDestroy()] provoqué par le système.

OnStop () doc dit " Notez que cette méthode peut ne jamais être appelée, dans des situations de mémoire insuffisante où le système n'a pas assez de mémoire pour maintenir le processus de votre activité en cours d'exécution après l'appel de sa méthode onPause (). "

Meryan
la source
PAS EXACTEMENT voir: stackoverflow.com/questions/12655898/…
ceph3us
2

Mon étude montre que cette finish()méthode place en fait certaines opérations de destruction dans la file d'attente, mais l'activité n'est pas détruite immédiatement. La destruction est cependant programmée.

Par exemple, si vous placez finish()dans onActivityResult()callback, while onResume()n'a pas encore exécuté, alors first onResume()sera exécuté, et seulement après cela onStop()et onDestroy()seront appelés.

REMARQUE: onDestroy()peut ne pas être appelé du tout, comme indiqué sur la documentation .

rommex
la source
2

appeler finish dans onCreate () n'appellera pas onDestroy () directement comme @prakash l'a dit. L' finish()opération ne commencera même pas tant que vous n'aurez pas rendu le contrôle à Android.

Appel de finish () dans onCreate () : onCreate () -> onStart () -> onResume () . Si l'utilisateur quitte l'application appelle -> onPause () -> onStop () -> onDestroy ()

Appel de finish () dans onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Appel de finish () dans onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Pour une vérification plus approfondie des références, regardez cette oncreate continue après la finition et à propos de la finition ()

anand krish
la source
0

Il semble que la seule réponse correcte jusqu'ici ait été donnée par romnex: "onDestroy () peut ne pas être appelé du tout". Même si en pratique, dans presque tous les cas, il n'y a aucune garantie: la documentation sur finish () promet seulement que le résultat de l'activité est propagé à l'appelant, mais rien de plus. De plus, la documentation du cycle de vie précise que l'activité peut être supprimée par le système d'exploitation dès que onStop () se termine (ou même plus tôt sur les appareils plus anciens), ce qui, même si peu probable et donc rare à observer dans un simple test, pourrait signifier que l'activité peut être tué pendant ou même avant l'exécution de onDestroy ().

Donc, si vous voulez vous assurer que du travail est fait lorsque vous appelez finish (), vous ne pouvez pas le mettre dans onDestroy (), mais vous devrez le faire au même endroit où vous appelez finish (), juste avant de l'appeler.

urps
la source
-4

finish () renvoie simplement à l'activité précédente dans Android, ou vous pouvez peut-être dire que cela fait un pas en arrière dans l'application

kapil
la source