O que o método Activity.finish () está fazendo exatamente?

156

Estou desenvolvendo aplicativos para Android por um tempo e segui várias postagens sobre o ciclo de vida da atividade e o ciclo de vida do aplicativo.

Conheço Activity.finish()chamadas de método em algum lugar no caminho Activity.onDestroy(), e também removo a atividade da pilha, e acho que, de alguma forma, aponta para o sistema operacional e o coletor de lixo que ele pode "fazer seu truque" e liberar a memória quando achar conveniente tão....

Eu vim para este post - Sair de um aplicativo com desdém? e leia a resposta de Mark Murphy.

Isso me deixou um pouco confuso sobre o que exatamente o finish()método realmente faz.

Existe uma chance de eu ligar finish()e onDestroy()não ser chamado?

Tal Kanel
fonte

Respostas:

171

Ao chamar finish()uma atividade, o método onDestroy()é executado. Este método pode fazer coisas como:

  1. Ignore todas as caixas de diálogo que a atividade estava gerenciando.
  2. Feche todos os cursores que a atividade estava gerenciando.
  3. Feche qualquer caixa de diálogo de pesquisa aberta

Além disso, onDestroy()não é um destruidor. Na verdade, não destrói o objeto. É apenas um método chamado com base em um determinado estado. Portanto, sua instância ainda está ativa e muito bem * após a onDestroy()execução e o retorno da superclasse. O Android mantém os processos por perto, caso o usuário queira reiniciar o aplicativo, isso torna a fase de inicialização mais rápida. O processo não fará nada e, se precisar recuperar a memória, o processo será eliminado

K_Anas
fonte
5
então o método finish () apenas aciona a chamada para onDestroy () e é isso?
precisa
9
Sim, se você voltar para a Activity onCreate () será chamado.
Luis Pena
9
Finish () também chama onPause () e onStop ()?
Sr09:
36
Testei novamente e descobri que onPause (), onStop () e onDestroy () serão todos chamados em ordem depois que você chamar finish ().
Sam003
5
@Laurent onPause () e onStop () nem sempre são chamados. Veja minha observação na resposta abaixo
Prakash
77

Meus 2 centavos na resposta @K_Anas. Eu realizei um teste simples no método finish (). Métodos importantes de retorno de chamada listados no ciclo de vida da atividade

  1. Chamando finish () em onCreate (): onCreate () -> onDestroy ()
  2. Concluindo a chamada () em onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Concluindo a chamada () em onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

O que quero dizer é que as contrapartes dos métodos, juntamente com os métodos intermediários, são chamadas quando o finish () é executado.

por exemplo:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
Prakash
fonte
e se você chamar de terminar dentro da onPause? chamará onStop> onDestroy?
Rmpt 3/16
Essa tabela é realmente útil e descritiva (você precisa rolar um pouco para baixo) developer.android.com/reference/android/app/…
winklerrr
Eu próprio verifiquei que esta resposta está correta.
Sreekanth Karumanaghat
33

Observe também que, se você ligar para terminar () após uma intenção, não poderá voltar à atividade anterior com o botão "voltar"

startActivity(intent);
finish();
Dan veste Prada
fonte
Essa é exatamente a informação de que eu precisava, pois como tenho uma atividade que se conecta apenas ao google drive, ele faz as verificações e passa para a atividade principal (ou para a atividade de Configurações se houver um erro), portanto o usuário não pode voltar.
Francesco Marchetti-Stasi
1
@Francesco Marchetti-Stasi No seu caso, seria melhor substituir onBackPressed () e não chamar super.onBackPressed (), se o usuário não voltar.
Paulo
13

onDestroy()é destinado à limpeza final - liberando recursos que você pode, fechando conexões abertas, leitores, escritores, etc. Se você não o substituir, o sistema fará o que for necessário.

por outro lado, finish()apenas permite que o sistema saiba que o programador deseja que a corrente Activityseja concluída. E, portanto, chama onDestroy()depois disso.

Algo a observar:

não é necessário que apenas uma chamada para a finish()desencadeie onDestroy(). Não. Como sabemos, o sistema Android é livre para matar atividades se achar que existem recursos necessários à corrente Activityque precisam ser liberados.

Kazekage Gaara
fonte
1
você escreveu que finish () informa ao sistema que a atividade precisa ser concluída. então é como dizer "faça x = diga ao sistema para fazer x". Segundos: na sua resposta, parece que existe uma maneira de ligar para terminar (), e o sistema decidirá não ligar para Destroy ()? é possível?
precisa
Você acertou a primeira parte. Ligar finish()está dizendo ao sistema para finalizar o Activity. a parte "x" na sua declaração do é "terminar (destruir) o Activity". A segunda parte está errada. Na verdade, eu perdi uma palavra lá. Eu editei a resposta. onDestroy()não é apenas acionado por finish(), o sistema pode chamá-lo por conta própria também.
Kazekage Gaara
1
Acabei de ler sua adição à resposta. por enquanto votei a resposta de forma positiva, porque achei sua explicação interessante, mas gostaria de ver se outras pessoas têm mais alguma coisa a dizer sobre ela antes de marcá-la como "answerd". obrigado por agora :)
Tal Kanel
Então, após terminar (), todas as variáveis ​​nesta atividade serão destruídas, certo? Quando eu voltar a esta atividade mais uma vez, eles serão declarados ou inicializados novamente, certo?
Sibbs Gambling
3
Nota: se o sistema concluir o processo, onDestroy não poderá ser chamado. developer.android.com/reference/android/app/...
Kevin Lee
9

O método Finish () destruirá a atividade atual. Você pode usar esse método nos casos em que não deseja que essa atividade seja carregada repetidamente quando o usuário pressionar o botão Voltar. Basicamente, limpa a atividade da pilha.current.

Udit Kapahi
fonte
8

Além da resposta @rommex acima, também notei que finish() enfileira a destruição da Atividade e depende da prioridade da Atividade.

Se eu ligar finish()depois onPause(), eu vejo onStop()eonDestroy() liguei imediatamente.

Se eu ligar finish()depois onStop(), não vejoonDestroy() até 5 minutos depois.

Pela minha observação, parece que o acabamento está na fila e, quando olhei para adb shell dumpsys activity activitiesele, estava definido comofinishing=true , mas como não está mais em primeiro plano, não foi priorizado para destruição.

Em resumo, onDestroy()nunca é garantido que seja chamado, mas, mesmo no caso em que é chamado, pode ser adiado.

Brandon Lim
fonte
5

Várias respostas e notas estão reivindicando que finish () pode pular onPause () e onStop () e executar diretamente onDestroy (). Para ser justo, a documentação do Android ( http://developer.android.com/reference/android/app/Activity.html ) observa "A atividade está sendo finalizada ou destruída pelo sistema", o que é bastante ambíguo, mas pode sugerir que finish () pode pular para onDestroy ().

O JavaDoc em finish () é igualmente decepcionante ( http://developer.android.com/reference/android/app/Activity.html#finish () ) e, na verdade, não observa quais métodos são chamados em resposta ao final ()

Então, escrevi este mini-aplicativo abaixo do qual registra cada estado na entrada. Ele inclui um botão que chama terminar () - para que você possa ver os logs de quais métodos foram acionados. Este experimento teria sugerido que acabamento () , de fato, também chamada onPause () e onStop (). Aqui está a saída que recebo:

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

@ user3282164 De acordo com o ciclo de vida da Atividade , ele deve passar por onPause()-> onStop()-> onDestroy()ao ligar finish().

O diagrama não mostra nenhum caminho reto de [Activity Running] para [ onDestroy()] causado pelo sistema.

O documento onStop () diz " Observe que esse método nunca pode ser chamado, em situações de pouca memória em que o sistema não possui memória suficiente para manter o processo da sua atividade em execução após a chamada do método onPause (). "

Meryan
fonte
NÃO EXATAMENTE, consulte: stackoverflow.com/questions/12655898/…
ceph3us
2

Meu estudo mostra que o finish()método realmente coloca algumas operações de destruição na fila, mas a Atividade não é destruída imediatamente. A destruição está agendada.

Por exemplo, se você colocar finish()no onActivityResult()callback, enquanto onResume()ainda tem de executar, então primeiro onResume()será executado, e só depois disso onStop()eonDestroy() são chamados.

NOTA: onDestroy()pode não ser necessário, como indicado na documentação .

rommex
fonte
2

chamar terminar em onCreate () não chamará onDestroy () diretamente como disse @prakash. ofinish() operação nem começará até você retornar o controle para o Android.

A conclusão de chamada () em onCreate () : onCreate () -> onStart () -> onResume () . Se o usuário sair do aplicativo, chamará -> onPause () -> onStop () -> onDestroy ()

Concluindo a chamada () em onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Concluindo a chamada () em onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Para referência adicional, verifique este oncreate contínuo após o término e sobre o término ()

anand krish
fonte
0

Parece que a única resposta correta aqui até agora foi dada pelo romnex: "onDestroy () pode nem ser chamado". Embora na prática, em quase todos os casos, não haja garantia: a documentação em finish () promete apenas que o resultado da atividade seja propagado de volta ao chamador, mas nada mais. Além disso, a documentação do ciclo de vida esclarece que a atividade é passível de matança pelo sistema operacional assim que o onStop () termina (ou mesmo mais cedo em dispositivos mais antigos), o que, apesar de improvável e, portanto, raro de observar em um teste simples, pode significar que a atividade pode ser morto enquanto ou antes de onDestroy () ser executado.

Portanto, se você quiser garantir que algum trabalho seja feito quando você chamar finish (), não poderá colocá-lo em onDestroy (), mas precisará fazê-lo no mesmo local em que você chama finish (), antes de realmente chamá-lo.

urps
fonte
-4

finish () apenas envia de volta à atividade anterior no android, ou pode ser que você possa dizer que está dando um passo atrás no aplicativo

Kapil
fonte