web-dev-qa-db-fra.com

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

Je développe des applications Android pendant un certain temps 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 méthode Activity.finish() 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 au système d'exploitation et au ramasse-miettes qu'il peut "faire son tour" et libérer la mémoire lorsqu'il le trouve utile le temps de le faire .... 

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

Cela m'a laissé un peu perplexe quant à ce que fait exactement la méthode finish().

Existe-t-il une chance que j'appelle finish() et que onDestroy() ne soit pas appelé?

134
Tal Kanel

Lorsque vous appelezfinish()pour une activité, la méthodeonDestroy()est exécutée. Cette méthode peut effectuer les opérations suivantes:

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

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

147
K_Anas

Mes 2 cents sur la réponse de @K_Anas . J'ai effectué un test simple sur la méthode finish () . Énuméré les 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 contreparties 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()
61
Prakash

Notez également que si vous appelez finish () après une intention, vous ne pouvez pas revenir à l'activité précédente avec le bouton "Précédent".

startActivity(intent);
finish();
13
Dan Wears Prada

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

par ailleurs, finish() indique simplement au système que le programmeur veut que la Activity courante soit terminée. Et par conséquent, il appelle onDestroy() après cela.

Quelque chose à noter:

il n'est pas nécessaire que seulement un appel à finish() déclenche un appel à onDestroy(). Comme nous le savons, le système Android est libre de tuer des activités s’il estime que la Activity actuelle a besoin de ressources pour pouvoir être libérées.

12
Kazekage Gaara

La méthode Finish () détruira l'activité en cours . Vous pouvez utiliser cette méthode dans les cas où vous ne voulez pas que cette activité soit chargée et relancée lorsque l'utilisateur appuie sur le bouton précédent . En gros, elle efface l'activité de la.current. empiler.

6
Udit Kapahi

Diverses réponses et notes affirment que finish () peut ignorer 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 «L’activité est en train de se terminer ou est en train d’être détruite par le système», ce qui est assez ambigu. mais pourrait suggérer que finish () peut aller à onDestroy (). 

La JavaDoc sur finish () est également décevante ( http://developer.Android.com/reference/Android/app/Activity.html#finish () ) et ne note pas en fait la ou les méthodes appelées. en réponse à finish ().

Donc, j'ai écrit cette mini-application ci-dessous qui enregistre chaque état lors de l'entrée. Il inclut un bouton qui appelle finish () - vous pouvez ainsi voir les journaux des méthodes qui sont déclenchées. Cette expérience suggérerait que finish () ne appelle effectivement aussi onPause () et onStop (). Voici la sortie que je reçois:

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

}
4
CoderOfTheNight

@ user3282164 Selon le cycle de vie Activité , il devrait passer par onPause() -> onStop() -> onDestroy() lors de l'appel de finish().

Le diagramme n'indique 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 jamais être appelée, dans les situations de mémoire insuffisante où le système ne dispose pas de suffisamment de mémoire pour que le processus de votre activité s'exécute après son onPause. La méthode () est appelée. "

3
Marie

Mon étude montre que la méthode finish() place en réalité des opérations de destruction dans la file d'attente, mais que l'activité n'est pas détruite immédiatement. La destruction est prévue cependant.

Par exemple, si vous placez finish() dans le callback onActivityResult(), alors que onResume() n'a pas encore été exécuté, le premier onResume() sera exécuté, et uniquement après que onStop() et onDestroy() seront appelés.

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

2
rommex

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

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

Si j'appelle finish() après onStop(), je ne vois pas onDestroy() avant 5 minutes. 

De mon point de vue, il semble que la fin soit en file d'attente et lorsque j'ai regardé le adb Shell dumpsys activity activities, il était réglé sur finishing=true, mais comme il n'est plus au premier plan, la destruction n'était pas prioritaire. 

En résumé, il n'est jamais garanti que l'appel de onDestroy() soit fait, mais même si c'est le cas, l'appel pourrait être retardé. 

1
Brandon Lim

l'appel de finish dans onCreate () n'appelle pas onDestroy () directement comme @prakash l'a dit. L'opération finish() ne commencera même pas jusqu'à ce que vous rendiez le contrôle à Android.

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

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

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

Pour plus de références, regardez ceci oncreate continu après finish & about finish ()

1
anand krish

Il semble que la seule réponse correcte à ce jour ait été donnée par romnex: "onDestroy () peut ne pas être appelé du tout". Même si dans la pratique, dans presque tous les cas, il n'y a aucune garantie. Le documentation on finish () ne fait que promettre que le résultat de l'activité est renvoyé à l'appelant, mais rien de plus. De plus, la documentation de lifecycle précise que l’activité peut être interrompue par le système d’exploitation dès la fin de onStop () (ou même avant sur les périphériques plus anciens), ce qui, même si cela est improbable et donc rare dans un simple test, pourrait signifie que l'activité peut être supprimée 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 à l'endroit même où vous appelez finish (), juste avant de l'appeler.

0
urps