Что именно делает метод Activity.finish ()?


156

Я занимаюсь разработкой приложений для Android некоторое время и следил за множеством постов о жизненном цикле активности и жизненном цикле приложения.

Я знаю, что Activity.finish()вызовы методов где-то на пути Activity.onDestroy(), а также удаление активности из стека, и я предполагаю, что это как-то указывает на операционную систему и сборщик мусора, которые он может "сделать свое дело" и освободить память, когда он находит, что это хорошее время, делая так....

Я пришел к этому сообщению - не одобряется ли выход из приложения? и прочитайте ответ Марка Мерфи.

Это немного смутило меня из-за того, что именно finish()делает метод.

Есть ли шанс, что я позвоню finish()и onDestroy()не позвоню ?


Ответы:


171

При вызове finish()действия метод onDestroy()выполняется. Этот метод может делать такие вещи, как:

  1. Откажитесь от любых диалогов, которыми управляла деятельность.
  2. Закройте все курсоры, которыми управляла деятельность.
  3. Закройте любой открытый диалог поиска

Кроме того, onDestroy()не деструктор. Это на самом деле не разрушает объект. Это просто метод, который вызывается на основе определенного состояния. Таким образом, ваш экземпляр все еще жив и очень хорошо * после onDestroy()запуска и возврата суперкласса. Android поддерживает процессы в случае, если пользователь захочет перезапустить приложение, это ускоряет этап запуска. Процесс не будет ничего делать, и если память потребуется восстановить, процесс будет убит


5
так что метод finish () вызывает только вызов onDestroy () и все?
Тал Канел

9
Да, если вы вернетесь в Activity, будет вызван onCreate ().
Луис Пена

9
Также метод finish () также вызывает onPause () и onStop ()?
sr09

36
Я протестировал еще раз и обнаружил, что onPause (), onStop () и onDestroy () будут вызываться по порядку после вызова finish ().
Sam003

5
@Laurent onPause () и onStop () не всегда вызываются. Смотрите мое наблюдение в ответе ниже
Пракаш

77

Мои 2 цента на @K_Anas отвечают. Я выполнил простой тест на метод finish (). Перечисленные важные методы обратного вызова в жизненном цикле деятельности

  1. Вызов метода finish () в onCreate (): onCreate () -> onDestroy ()
  2. Вызов метода finish () в onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Вызов метода finish () в onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Что я хочу сказать, так это то, что аналоги методов вместе с любыми методами между ними вызываются при выполнении finish ().

например:

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

Что делать, если вы вызываете финиш внутри onPause? это будет вызывать onStop> onDestroy?
rmpt

Эта таблица действительно полезна и
наглядна

Я сам проверил, что этот ответ правильный.
Sreekanth Karumanaghat

33

Также обратите внимание, что если вы вызываете finish () после намерения, вы не можете вернуться к предыдущему действию с помощью кнопки «назад».

startActivity(intent);
finish();

Это именно та информация, которая мне была нужна, так как у меня есть действие, которое подключается только к Google Drive, затем выполняет свои проверки и переходит к основному действию (или к действию Настройки в случае ошибки), поэтому пользователь должен не смогу вернуться
Франческо Маркетти-Штази

1
@Francesco Marchetti-Stasi В вашем случае было бы лучше переопределить onBackPressed () и не вызывать super.onBackPressed (), если пользователь не должен возвращаться назад.
Пол

13

onDestroy()предназначен для окончательной очистки - освобождения ресурсов, которые вы можете самостоятельно, закрытия открытых соединений, читателей, писателей и т. д. Если вы не переопределите это, система сделает то, что должна.

с другой стороны, finish()просто сообщает системе, что программист хочет, чтобы ток Activityбыл завершен. И, следовательно, он вызываетonDestroy() после этого.

На что обратить внимание:

не обязательно, чтобы только вызов finish()инициировал вызов onDestroy(). Нет. Как мы знаем, система Android может свободно убивать действия, если она чувствует, что существуют ресурсы, необходимые для тока Activity, которые необходимо освободить.


1
Вы написали, что finish () сообщает системе, что действие должно быть завершено. так что все равно, что сказать "do x = сказать системе сделать x". секундная вещь: из вашего ответа звучит так, будто есть способ, которым я буду вызывать finish (), и система решит не вызывать onDestroy ()? Является ли это возможным?
Тал Канел

Вы правильно поняли первую часть. Звонок finish()говорит системе закончить Activity. часть «x» в вашем утверждении do - «закончить (уничтожить) Activity». Вторая часть неверна. На самом деле, я пропустил там слово. Я отредактировал ответ. onDestroy()не только вызывается finish(), система может вызывать это и сама.
Казекаге Гаара

1
Я только что прочитал ваше дополнение к ответу. сейчас я проголосовал за ответ, потому что я нашел ваше объяснение интересным, но я хотел бы узнать, могут ли другие сказать что-то еще об этом, прежде чем пометить его как «отвеченный». спасибо за сейчас :)
Tal Kanel

Таким образом, после завершения () все переменные в этом действии будут уничтожены, верно? Когда я снова вернусь к этим действиям, они будут повторно объявлены или инициализированы, верно?
Сиббс, азартные игры,

3
Примечание: если система убивает процесс, onDestroy может не вызываться. developer.android.com/reference/android/app/…
Кевин Ли,

9

Метод Finish () уничтожит текущую активность. Вы можете использовать этот метод в тех случаях, когда вы не хотите, чтобы это действие загружалось снова и снова, когда пользователь нажимает кнопку «Назад». В основном это очищает активность от стека .current.


8

В дополнение к ответу @rommex выше, я также заметил, что finish()очередь уничтожает активность и что она зависит от приоритета активности.

Если я позвоню finish()после onPause(), я увижу onStop()и onDestroy()сразу позвоню .

Если я позвоню finish()после onStop(), я не увижу onDestroy()до 5 минут спустя.

По моим наблюдениям, похоже, что финиш поставлен в очередь, и когда я посмотрел на adb shell dumpsys activity activitiesнего, он был установлен finishing=true, но, поскольку он больше не находится на переднем плане, он не был приоритетным для уничтожения.

Таким образом, onDestroy()никогда не гарантируется, что он будет вызван, но даже в случае его вызова он может быть отложен.


5

В различных ответах и ​​примечаниях утверждается, что finish () может пропускать onPause () и onStop () и напрямую выполнять onDestroy (). Чтобы быть справедливым, документация Android на этом ( http://developer.android.com/reference/android/app/Activity.html ) отмечается, что «активность завершается или уничтожается системой», что довольно неоднозначно, но может указывать, что отделка () может перейти к onDestroy ().

JavaDoc на finish () также разочаровывает ( http://developer.android.com/reference/android/app/Activity.html#finish () ) и фактически не отмечает, какие методы были вызваны в ответ на finish ().

Итак, я написал это мини-приложение ниже, которое регистрирует каждое состояние при входе. Она включает в себя кнопку, которая вызывает метод finish (), чтобы вы могли видеть журналы запускаемых методов. Этот эксперимент показал бы, что finish () действительно также вызывает onPause () и onStop (). Вот результат, который я получаю:

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 В соответствии с жизненным циклом Активности, он должен пройти onPause()-> onStop()-> onDestroy()после вызова finish().

Диаграмма не показывает прямой путь от [Activity Running] до [ onDestroy()], вызванный системой.

В onStop () doc говорится: « Обратите внимание, что этот метод никогда не может быть вызван в ситуациях с нехваткой памяти, когда системе не хватает памяти для поддержания процесса вашей активности после вызова метода onPause () ».



2

Мое исследование показывает, что finish() метод фактически помещает некоторые операции уничтожения в очередь, но действие не уничтожается немедленно. Уничтожение запланировано, хотя.

Например, если вы поместите finish()в onActivityResult()обратный вызов, пока onResume()еще не запустили, то сначала onResume()будет выполняться, и только после этого onStop()и onDestroy()будут вызваны.

ПРИМЕЧАНИЕ: onDestroy()может не вызываться вообще, как указано в документации .


2

вызов метода finish в onCreate () не вызовет onDestroy () напрямую, как сказал @prakash. finish()Операция не будет даже начинать , пока не возвращает управление Android.

Вызов метода finish () в onCreate () : onCreate () -> onStart () -> onResume () . При выходе пользователя приложение вызовет -> onPause () -> onStop () -> onDestroy ()

Вызов метода finish () в onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Вызов метода finish () в onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Для дальнейшей справочной проверки посмотрите на это непрерывное создание после окончания и около конца ()


0

Похоже, что пока единственно правильный ответ дал romnex: «onDestroy () может вообще не вызываться». Несмотря на то, что на практике почти во всех случаях это не гарантируется: документация на finish () обещает только то, что результат действия будет передан обратно вызывающей стороне, но не более того. Более того, в документации жизненного цикла разъясняется, что эта операция уничтожается ОС, как только завершается onStop () (или даже раньше на старых устройствах), что, хотя и маловероятно, а потому редко наблюдается в простом тесте, может означать, что активность может быть убит во время или даже до выполнения onDestroy ().

Поэтому, если вы хотите убедиться, что какая-то работа выполнена, когда вы вызываете finish (), вы не можете поместить ее в onDestroy (), но вам нужно будет сделать то же самое место, где вы вызываете finish (), прямо перед тем, как вызвать ее.


-4

finish () просто отправляет обратно к предыдущему действию в Android, или, может быть, вы можете сказать, что он возвращается на шаг назад в приложении

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.