¿Qué está haciendo exactamente el método Activity.finish ()?

156

Estoy desarrollando aplicaciones de Android por un tiempo y seguí muchas publicaciones sobre el ciclo de vida de la actividad y el ciclo de vida de la aplicación.

Sé que el Activity.finish()método llama en algún momento Activity.onDestroy(), y también elimina la actividad de la pila, y supongo que de alguna manera apunta al sistema operativo y al recolector de basura que puede "hacer su truco" y liberar la memoria cuando lo encuentre un buen momento. entonces....

Llegué a esta publicación: ¿está mal visto salir de una aplicación? y lee la respuesta de Mark Murphy.

Me confundió un poco lo que hace exactamente el finish()método.

¿Hay alguna posibilidad de que llame finish()y onDestroy()no sea llamado?

Tal Kanel
fuente

Respuestas:

171

Cuando se llama finish()a una actividad, el método onDestroy()se ejecuta. Este método puede hacer cosas como:

  1. Descarte los diálogos que la actividad estaba gestionando.
  2. Cierre los cursores que la actividad administraba.
  3. Cerrar cualquier diálogo de búsqueda abierto

Además, onDestroy()no es un destructor. En realidad no destruye el objeto. Es solo un método que se llama en función de un determinado estado. Por lo tanto, su instancia aún está viva y muy bien * después de que la superclase se onDestroy()ejecute y regrese. Android mantiene los procesos en caso de que el usuario quiera reiniciar la aplicación, esto hace que la fase de inicio sea más rápida. El proceso no hará nada y si la memoria necesita ser recuperada, el proceso será anulado.

K_Anas
fuente
55
así que el método finish () solo activa la llamada a onDestroy () y eso es todo.
Tal Kanel
9
Sí, si vuelve a la Actividad, se llamará a onCreate ().
Luis Peña
9
¿Fin () también llama a onPause () y onStop ()?
sr09
36
Lo probé nuevamente y descubrí que onPause (), onStop () y onDestroy () se llamarán en orden después de que llame a finish ().
Sam003
55
@Laurent onPause () y onStop () no siempre se llaman. Vea mi observación en la respuesta a continuación
Prakash
77

Mis 2 centavos en @K_Anas responden. Realicé una prueba simple en el método finish (). Enumeró métodos de devolución de llamada importantes en el ciclo de vida de la actividad.

  1. Llamar a finish () en onCreate (): onCreate () -> onDestroy ()
  2. Llamar a finish () en onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Llamar a finish () en onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Lo que quiero decir es que las contrapartes de los métodos junto con cualquier método intermedio se invocan cuando se ejecuta finish ().

p.ej:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
Prakash
fuente
¿Qué pasa si llamas a terminar dentro de onPause? llamará a onStop> onDestroy?
rmpt
Esa tabla es realmente útil y descriptiva (debe desplazarse un poco hacia abajo) developer.android.com/reference/android/app/…
winklerrr
Yo mismo he verificado que esta respuesta es correcta.
Sreekanth Karumanaghat
33

También tenga en cuenta que si llama a finish () después de un intento, no puede volver a la actividad anterior con el botón "atrás"

startActivity(intent);
finish();
Dan viste de Prada
fuente
Esta es exactamente la información que necesitaba, ya que tengo una actividad que solo se conecta a Google Drive, luego realiza sus comprobaciones y pasa a la actividad principal (o a la actividad Configuración si hay un error), por lo que el usuario no debería No poder volver.
Francesco Marchetti-Stasi
1
@Francesco Marchetti-Stasi En su caso, sería mejor anular onBackPressed () y no llamar a super.onBackPressed () si el usuario no debe regresar.
Paul
13

onDestroy()está destinado a la limpieza final: liberar recursos que pueda por su cuenta, cerrar conexiones abiertas, lectores, escritores, etc. Si no lo anula, el sistema hace lo que tiene que hacer.

Por otro lado, finish()solo le dice al sistema que el programador quiere que la corriente Activityse termine. Y por lo tanto, se llama onDestroy()después de eso.

Algo a tener en cuenta:

no es necesario que solo una llamada a finish()active una llamada a onDestroy(). No. Como sabemos, el sistema Android es libre de matar actividades si considera que la corriente necesita recursos Activitypara liberarlos.

Kazekage Gaara
fuente
1
usted escribió que finish () le hizo saber al sistema que la actividad necesita ser terminada. entonces es como decir "do x = decirle al sistema que haga x". segundos: por su respuesta, parece que hay una forma de llamar a terminar (), y el sistema decidirá no llamar a onDestroy ()? ¿Es posible?
Tal Kanel
Tienes la primera parte correcta. Llamar finish()es decirle al sistema que finalice el Activity. la parte "x" en su declaración do es "terminar (destruir) el Activity". La segunda parte está mal. En realidad, me perdí una palabra allí. He editado la respuesta. onDestroy()no solo se activa finish(), el sistema también puede llamarlo por sí mismo.
Kazekage Gaara
1
Acabo de leer tu adición a la respuesta. por ahora he votado a favor la respuesta porque he encontrado interesante su explicación, pero me gustaría ver si los demás tienen algo más que decir al respecto antes de marcarla como "contestada". gracias por ahora :)
Tal Kanel
Entonces, después de terminar (), todas las variables en esta actividad serán destruidas, ¿verdad? Cuando vuelva a esta actividad una vez más, se volverán a declarar o inicializar, ¿verdad?
Sibbs Gambling
3
Nota: si el sistema mata el proceso, no se puede llamar a onDestroy. developer.android.com/reference/android/app/…
Kevin Lee
9

El método Finish () destruirá la actividad actual. Puede usar este método en los casos en que no desea que esta actividad se cargue una y otra vez cuando el usuario presiona el botón Atrás. Básicamente, borra la actividad de la pila actual.

Udit Kapahi
fuente
8

Además de la respuesta @rommex anterior, también he notado que finish() pone en cola la destrucción de la Actividad y que depende de la prioridad de la Actividad.

Si llamo finish()después onPause(), veo onStop(), yonDestroy() inmediatamente llamé.

Si llamo finish()después onStop(), no veoonDestroy() hasta 5 minutos después.

Desde mi observación, parece que el final está en cola y cuando miré el adb shell dumpsys activity activitiesestaba configuradofinishing=true , pero como ya no está en primer plano, no se priorizó para la destrucción.

En resumen, onDestroy()nunca se garantiza que se llame, pero incluso en el caso de que se llame, podría retrasarse.

Brandon Lim
fuente
5

Varias respuestas y notas afirman que finish () puede omitir onPause () y onStop () y ejecutar directamente onDestroy (). Para ser justos, la documentación de Android sobre esto ( http://developer.android.com/reference/android/app/Activity.html ) señala "La actividad está terminando o está siendo destruida por el sistema", lo cual es bastante ambiguo pero podría sugerir que terminar () puede saltar a onDestroy ().

El JavaDoc en finish () es igualmente decepcionante ( http://developer.android.com/reference/android/app/Activity.html#finish () ) y en realidad no observa qué método (s) se llaman en respuesta al final ()

Así que escribí esta mini aplicación a continuación que registra cada estado a la entrada. Incluye un botón que llama a terminar (), para que pueda ver los registros de los métodos que se activan. Este experimento sugiere que la meta () en efecto también llamada onPause () y onStop (). Aquí está la salida que obtengo:

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
fuente
3

@ user3282164 De acuerdo con el ciclo de vida de la Actividad , debe pasar por onPause()-> onStop()-> onDestroy()al llamar finish().

El diagrama no muestra ninguna ruta directa desde [Actividad en ejecución] a [ onDestroy()] causada por el sistema.

onStop () doc dice " Tenga en cuenta que este método nunca se puede llamar, en situaciones de poca memoria donde el sistema no tiene suficiente memoria para mantener el proceso de su actividad en ejecución después de que se llama a su método onPause () " .

Meryan
fuente
NO EXACTAMENTE ver: stackoverflow.com/questions/12655898/…
ceph3us
2

Mi estudio muestra que el finish()método en realidad coloca algunas operaciones de destrucción en la cola, pero la Actividad no se destruye de inmediato. Sin embargo, la destrucción está programada.

Por ejemplo, si realiza una devolución finish()de onActivityResult()llamada, mientras onResume()aún no se ha ejecutado, primero onResume()se ejecutará, y solo después de eso onStop()y onDestroy()se llamará.

NOTA: onDestroy()no se puede llamar en absoluto, como se indica en la documentación .

rommex
fuente
2

la llamada finalizar en onCreate () no llamará a onDestroy () directamente como dijo @prakash. losfinish() operación ni siquiera comenzará hasta que regrese el control a Android.

Llamar a finish () en onCreate () : onCreate () -> onStart () -> onResume () . Si la salida de usuario de la aplicación va a llamar -> onPause () -> onStop () -> OnDestroy ()

Llamar a finish () en onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Llamar a finish () en onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Para mayor referencia, verifique este oncreate continuo después del acabado y sobre el acabado ()

anand krish
fuente
0

Parece que la única respuesta correcta aquí hasta ahora ha sido dada por romnex: "onDestroy () puede no ser llamado en absoluto". Aunque en la práctica, en casi todos los casos lo hará, no hay garantía: la documentación en finish () solo promete que el resultado de la actividad se propaga de nuevo a la persona que llama, pero nada más. Además, la documentación del ciclo de vida aclara que el sistema operativo puede eliminar la actividad tan pronto como termine onStop () (o incluso antes en dispositivos más antiguos), lo que, aunque es poco probable y, por lo tanto, raro de observar en una prueba simple, podría significar que la actividad puede ser asesinado mientras o incluso antes de que se ejecute onDestroy ().

Entonces, si desea asegurarse de que se realice algún trabajo cuando llame a finish (), no puede colocarlo en onDestroy (), pero deberá hacerlo en el mismo lugar donde llama a finish (), justo antes de llamarlo.

urps
fuente
-4

terminar () simplemente envía de vuelta a la actividad anterior en Android, o puede decir que está retrocediendo un paso en la aplicación

kapil
fuente