Che cosa fa esattamente il metodo Activity.finish ()?


156

Sto sviluppando applicazioni Android da un po 'e ho seguito molti post sul ciclo di vita delle attività e sul ciclo di vita delle applicazioni.

Conosco Activity.finish()metodi che chiamano da qualche parte Activity.onDestroy(), e anche rimuovendo l'attività dallo stack, e immagino che in qualche modo punti al sistema operativo e al garbage collector che può "fare il suo trucco" e liberare la memoria quando lo trova un buon momento così....

Sono arrivato a questo post - La chiusura di una domanda è disapprovata? e leggi la risposta di Mark Murphy.

Mi ha reso un po 'confuso su cosa fa esattamente il finish()metodo.

C'è una possibilità che chiamerò finish()e onDestroy()non verrà chiamato?


Risposte:


171

Quando si chiama finish()un'attività, il metodo onDestroy()viene eseguito. Questo metodo può fare cose come:

  1. Chiudi tutte le finestre di dialogo gestite dall'attività.
  2. Chiudi tutti i cursori che l'attività stava gestendo.
  3. Chiudi qualsiasi finestra di ricerca aperta

Inoltre, onDestroy()non è un distruttore. In realtà non distrugge l'oggetto. È solo un metodo chiamato basato su un certo stato. Quindi la tua istanza è ancora viva e molto bene * dopo l' onDestroy()esecuzione e la restituzione della superclasse . Android mantiene i processi in giro nel caso in cui l'utente desideri riavviare l'app, questo rende la fase di avvio più veloce. Il processo non farà nulla e se la memoria deve essere recuperata, il processo verrà ucciso


5
quindi il metodo finish () attiva solo la chiamata a onDestroy () e il gioco è fatto?
Tal Kanel,

9
Sì, se torni a Activity onCreate () verrà chiamato.
Luis Pena,

9
Finish () chiama anche onPause () e onStop ()?
sr09,

36
Ho provato di nuovo e ho scoperto che onPause (), onStop () e onDestroy () verranno tutti chiamati in ordine dopo aver chiamato finish ().
Sam003,

5
@Laurent onPause () e onStop () non sono sempre chiamati. Vedi la mia osservazione nella risposta di seguito
Prakash,

77

I miei 2 centesimi sulla risposta di @K_Anas. Ho eseguito un semplice test sul metodo finish (). Elencati importanti metodi di callback nel ciclo di vita delle attività

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

Quello che intendo dire è che le controparti dei metodi insieme a tutti i metodi in mezzo vengono chiamati quando viene eseguito finish ().

per esempio:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()

cosa succede se si chiama finish inside onPause? chiamerà onStop> onDestroy?
rmpt

Quella tabella è davvero utile e descrittiva (devi scorrere un po 'verso il basso) developer.android.com/reference/android/app/…
winklerrr

Io stesso ho verificato che questa risposta è corretta.
Sreekanth Karumanaghat,

33

Notare anche se si chiama finish () dopo un intento che non è possibile tornare all'attività precedente con il pulsante "indietro"

startActivity(intent);
finish();

Queste sono esattamente le informazioni di cui avevo bisogno, poiché ho un'attività che si collega solo a google drive, quindi fa i suoi controlli e passa all'attività principale (o all'attività Impostazioni in caso di errore), quindi l'utente non dovrebbe essere in grado di tornare indietro.
Francesco Marchetti-Stasi,

1
@Francesco Marchetti-Stasi Nel tuo caso sarebbe meglio sovrascrivere onBackPressed () e non chiamare super.onBackPressed () se l'utente non dovesse tornare indietro.
Paul

13

onDestroy()è pensato per la pulizia finale: liberare risorse che puoi da solo, chiudere connessioni aperte, lettori, scrittori, ecc. Se non lo sostituisci, il sistema fa quello che deve.

d'altra parte, finish()fa semplicemente sapere al sistema che il programmatore vuole che la corrente Activitysia finita. E quindi, richiama onDestroy()dopo quello.

Qualcosa da notare:

non è necessario che solo una chiamata finish()attivi una chiamata onDestroy(). No. Come sappiamo, il sistema Android è libero di uccidere le attività se sente che ci sono risorse necessarie alla corrente Activityche sono necessarie per essere liberate.


1
hai scritto che finish () fa sapere al sistema che l'attività deve essere finita. quindi è come dire "do x = dì al sistema di fare x". secondi cosa: dalla tua risposta sembra che ci sia un modo che chiamerò finish (), e il sistema deciderà di non chiamare onDestroy ()? È possibile?
Tal Kanel,

Hai ottenuto la prima parte giusta. La chiamata finish()sta dicendo al sistema di terminare Activity. la parte "x" nell'istruzione do è "per finire (distruggere) il Activity". La seconda parte è sbagliata. In realtà, ho perso una parola lì. Ho modificato la risposta. onDestroy()non è solo attivato da finish(), il sistema può chiamarlo anche da solo.
Kazekage Gaara,

1
Ho appena letto la tua aggiunta alla risposta. per ora ho votato a favore della risposta perché ho trovato la tua spiegazione interessante, ma vorrei vedere se gli altri avrebbero qualcos'altro da dire al riguardo prima di contrassegnarlo come "answerd". grazie per ora :)
Tal Kanel,

Quindi, dopo finish (), tutte le variabili in questa attività verranno distrutte, giusto? Quando torno nuovamente a questa attività, verranno nuovamente dichiarati o inizializzati, giusto?
Sibbs Gioco d'azzardo il

3
Nota: se il sistema termina il processo, onDestroy potrebbe non essere chiamato. developer.android.com/reference/android/app/…
Kevin Lee

9

Il metodo Finish () distruggerà l'attività corrente. È possibile utilizzare questo metodo nei casi in cui non si desidera caricare questa attività più volte quando l'utente preme il pulsante Indietro. Fondamentalmente cancella l'attività dallo stack corrente.


8

Oltre alla risposta @rommex sopra, ho anche notato che finish()mette in coda la distruzione dell'attività e che dipende dalla priorità dell'attività.

Se chiamo finish()dopo onPause(), vedo onStop(), e onDestroy()immediatamente chiamato.

Se chiamo finish()dopo onStop(), non vedo onDestroy()fino a 5 minuti dopo.

Dalla mia osservazione, sembra che il traguardo sia in coda e quando l'ho guardato adb shell dumpsys activity activitiesera impostato su finishing=true, ma poiché non è più in primo piano, non è stato dato la priorità alla distruzione.

In sintesi, onDestroy()non è mai garantito che venga chiamato, ma anche nel caso in cui venga chiamato, potrebbe essere ritardato.


5

Varie risposte e note sostengono che finish () può saltare onPause () e onStop () ed eseguire direttamente onDestroy (). Ad essere onesti, la documentazione Android su questo ( http://developer.android.com/reference/android/app/Activity.html ) osserva che "L'attività sta finendo o che viene distrutta dal sistema" che è piuttosto ambigua ma potrebbe suggerire che finish () può saltare a onDestroy ().

Allo stesso modo, JavaDoc su finish () è deludente ( http://developer.android.com/reference/android/app/Activity.html#finish () ) e in realtà non nota quali metodi sono chiamati in risposta a finish ().

Così ho scritto questa mini-app in basso che registra ogni stato all'entrata. Include un pulsante che chiama finish (), in modo da poter vedere i registri di quali metodi vengono attivati. Questo esperimento suggerirebbe che finish () in effetti chiama anche onPause () e onStop (). Ecco l'output che ottengo:

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 Secondo l' attività del ciclo di vita che dovrebbe passare attraverso onPause()-> onStop()-> onDestroy()su chiamando finish().

Il diagramma non mostra alcun percorso rettilineo da [Attività in esecuzione] a [ onDestroy()] causato dal sistema.

Il documento onStop () dice " Nota che questo metodo non può mai essere chiamato, in situazioni di memoria insufficiente in cui il sistema non ha memoria sufficiente per mantenere in esecuzione il processo della tua attività dopo che è stato chiamato il suo metodo onPause (). "



2

Il mio studio mostra che il finish()metodo inserisce effettivamente alcune operazioni di distruzione nella coda, ma l'attività non viene immediatamente distrutta. La distruzione è prevista però.

Ad esempio, se si inserisce finish()in onActivityResult()richiamata, mentre onResume()deve ancora correre, poi la prima onResume()verrà eseguito, e solo dopo che onStop()e onDestroy()sono chiamati.

NOTA: onDestroy()potrebbe non essere chiamato affatto, come indicato nella documentazione .


2

chiamando finish in onCreate () non chiamerà onDestroy () direttamente come ha detto @prakash. L' finish()operazione non inizierà nemmeno fino a quando non si ritorna il controllo su Android.

Chiamata finish () in onCreate () : onCreate () -> onStart () -> onResume () . Se l'utente esce dall'app, chiamerà -> onPause () -> onStop () -> onDestroy ()

Chiamata finish () in onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

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

Per ulteriori riferimenti di riferimento, guarda questo oncreate continuo dopo finitura e sulla finitura ()


0

Sembra che finora l'unica risposta corretta qui sia stata data da romnex: "onDestroy () potrebbe non essere chiamato affatto". Anche se in pratica, in quasi tutti i casi, non esiste alcuna garanzia: la documentazione su finish () promette solo che il risultato dell'attività viene propagato al chiamante, ma niente di più. Inoltre, la documentazione del ciclo di vita chiarisce che l'attività è eseguibile dal sistema operativo non appena onStop () termina (o anche prima su dispositivi più vecchi), che, sebbene improbabile e quindi raro da osservare in un semplice test, potrebbe significare che l'attività potrebbe essere ucciso mentre o anche prima dell'esecuzione di onDestroy ().

Quindi, se vuoi assicurarti che un po 'di lavoro venga fatto quando chiami finish (), non puoi metterlo in onDestroy (), ma dovrai farlo nello stesso posto in cui chiami finish (), proprio prima di chiamarlo.


-4

finish () rimanda semplicemente all'attività precedente in Android, oppure potresti dire che sta facendo un passo indietro nell'applicazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.