Що саме робить метод Activity.finish ()?


156

Я певний час розробляв додатки для Android, а також слідкував за багатьма публікаціями про життєвий цикл діяльності та життєвий цикл програми.

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

Я прийшов до цієї посади - Чи нахмурився вихід із програми? і прочитати відповідь Марка Мерфі.

Це мене трохи збентежило, що саме цей finish()метод насправді робить.

Чи є ймовірність, що я подзвоню, finish()і мені не дзвонять onDestroy()?


Пов'язана тематика - Як Activity.finish () працює в Android?
RBT

Відповіді:


171

При виклику finish()активності метод onDestroy()виконується. Цей метод може робити такі речі, як:

  1. Відхиліть усі діалоги, якими керувала діяльність.
  2. Закрийте будь-які курсори, якими керувала діяльність.
  3. Закрийте будь-яке відкрите діалогове вікно пошуку

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


5
так що закінчуйте () метод лише запускаючи виклик на onDestroy (), і це все?
Тал Канель

9
Так, якщо ви повернетесь до Activity onCreate (), вам буде викликано.
Луїс Пена

9
Чи завершує () також виклик OnPause () та onStop ()?
sr09

36
Я перевірив ще раз і виявив, що onPause (), onStop () і onDestroy () буде викликано по порядку, після того, як ви зателефонуєте закінчити ().
Sam003

5
@Laurent onPause () та onStop () не завжди викликаються. Дивіться моє спостереження у відповіді нижче
Пракаш

77

Мої 2 копійки на відповідь @K_Anas. Я провів простий метод тесту на фініш (). Перелічені важливі методи зворотного виклику в життєвому циклі діяльності

  1. Виклик закінчення () у onCreate (): onCreate () -> onDestroy ()
  2. Виклик закінчення () в onStart (): onCreate () -> onStart () -> onStop () -> onDestroy ()
  3. Виклик закінчення () у onResume (): onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Що я хочу сказати, це те, що аналоги методів разом з будь-якими методами між ними викликаються, коли завершується ().

наприклад:

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

що робити, якщо ви зателефонуєте закінчити всерединіПауза? він зателефонує onStop> onDestroy?
rmpt

Ця таблиця дійсно корисна і описова (потрібно трохи прокрутити вниз) developer.android.com/reference/android/app/…
winklerrr

Я сам переконався, що ця відповідь правильна.
Sreekanth Karumanaghat

33

Також зауважте, якщо ви зателефонували до закінчення () після наміру, ви не можете повернутися до попередньої діяльності кнопкою "назад"

startActivity(intent);
finish();

Це саме та інформація, яка мені була потрібна, оскільки у мене є діяльність, яка підключається лише до google-накопичувача, вона робить свої перевірки і переходить до основної діяльності (або до діяльності "Налаштування", якщо є помилка), тому користувач не повинен Я не зможу повернутися назад.
Франческо Маршетті-Штазі

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

13

onDestroy()призначений для остаточного очищення - звільнення ресурсів, які ви можете самостійно, закриття відкритих з’єднань, читачів, авторів тощо. Якщо ви не перекриєте її, система робить все, що їй належить.

з іншого боку, finish()просто дає системі знати, що програміст хоче Activityзакінчити струм . А значить, закликає onDestroy()після цього.

Що слід зазначити:

необов'язково, щоб тільки дзвінок finish()викликав виклик onDestroy(). Ні. Як ми знаємо, андроїдна система може вбивати діяльність, якщо відчуває, що є ресурси, необхідні струму Activity, які потрібні для звільнення.


1
Ви писали, що закінчуйте (), нехай система знає, яку діяльність потрібно закінчити. тож це як сказати "do x = сказати системі зробити x". секундна річ: з вашої відповіді це звучить так, що є спосіб, який я зателефоную до кінця (), і система вирішить не дзвонити наDestroy ()? Це можливо?
Тал Канель

Ви отримали першу частину правильно. Виклик finish()повідомляє системі закінчити Activity. частиною "x" у вашому операторі do є "закінчити (знищити) Activity". Друга частина неправильна. Насправді я пропустив там слово. Я відредагував відповідь. onDestroy()це не просто спрацьовує finish(), система може також викликати його самостійно.
Kazekage Gaara

1
Я щойно прочитав ваше доповнення до відповіді. поки що я проголосував відповідь, тому що я вважав ваше пояснення цікавим, але я хотів би побачити, чи не могли б інші сказати про це ще до того, як позначити його як "відповідь". дякую зараз :)
Tal Kanel

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

3
Примітка: якщо система вбиває процес, onDestroy може не викликатися. developer.android.com/reference/android/app/…
Кевін Лі

9

Метод Finish () знищить поточну активність. Цей метод можна використовувати в тих випадках, коли ви не хочете, щоб ця діяльність знову і знову завантажувалася, коли користувач натискає кнопку назад. В основному, це видаляє активність із стека потоків.


8

На додаток до відповіді @rommex вище, я також помітив, що в finish()черзі знищується активність, і що це залежить від пріоритету діяльності.

Якщо я дзвоню finish()після onPause(), я бачу onStop(), і onDestroy()негайно зателефонував.

Якщо я дзвоню finish()після onStop(), я не бачусь onDestroy()лише через 5 хвилин.

З мого спостереження, схоже, що фініш стоїть у черзі, і коли я подивився на нього, adb shell dumpsys activity activitiesвін був встановлений finishing=true, але, оскільки він більше не на передньому плані, він не став пріоритетним для руйнування.

Підсумовуючи, onDestroy()ніколи не гарантується дзвінок, але навіть у випадку, коли він викликаний, це може бути відкладено.


5

Різні відповіді та примітки стверджують, що закінчення () може пропустити onPause () та onStop () та безпосередньо виконати onDestroy (). Справедливості, документація на Android щодо цього ( http://developer.android.com/reference/android/app/Activity.html ) зазначає: "Діяльність закінчується або знищується системою", що є досить неоднозначним, але може припустити, що закінчення () може перейти до OnDestroy ().

JavaDoc на фініші () аналогічно розчаровує ( http://developer.android.com/reference/android/app/Activity.html#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() .

На діаграмі не відображається жоден прямий шлях від [Запуск активності] до [onDestroy() ], викликаний системою.

onStop () doc каже: " Зауважте, що цей метод ніколи не може бути застосований у ситуаціях з низькою пам'яттю, коли в системі недостатньо пам'яті, щоб тримати процес вашої активності після виклику методу onPause (). "



2

Моє дослідження показує, що finish()метод насправді ставить деякі операції знищення в чергу, але Діяльність не знищується відразу. Однак руйнування заплановано.

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

ПРИМІТКА: onDestroy()може взагалі не викликатися, як зазначено в документації .


2

завершення виклику в onCreate () не зателефонує onDestroy () безпосередньо, як сказав @prakash. finish()Операція не буде навіть починати , поки не повертає керування Android.

Виклик закінчення () у onCreate () : onCreate () -> onStart () -> onResume () . Якщо користувач вийде, програма зателефонує -> onPause () -> onStop () -> onDestroy ()

Виклик закінчення () у onStart () : onCreate () -> onStart () -> onStop () -> onDestroy ()

Виклик закінчення () у onResume () : onCreate () -> onStart () -> onResume () -> onPause () -> onStop () -> onDestroy ()

Для подальшого ознайомлення перевірте це на створеному безперервному після закінчення та про закінчення ()


0

Здається, що єдину правильну відповідь тут поки що дав romnex: "onDestroy () може взагалі не називатися". Незважаючи на те, що на практиці майже у всіх випадках це є, гарантії немає: Документація про закінчення () лише обіцяє, що результат діяльності буде переданий абоненту, але більше нічого. Більше того, документація щодо життєвого циклу пояснює, що діяльність може бути відхилена операційною системою, як тільки onStop () закінчується (або навіть раніше на старих пристроях), що, хоч і малоймовірно і тому рідко спостерігається в простому тесті, може означати, що активність може бути вбита під час або навіть до того, як буде виконано onDestroy ().

Отже, якщо ви хочете переконатися, що якась робота виконується під час виклику закінчення (), ви не можете поставити її в onDestroy (), але це потрібно зробити в тому самому місці, де ви викликаєте закінчення (), безпосередньо перед тим, як його фактично викликати.


-4

закінчення () просто повертається до попередньої діяльності в android, або, можливо, ви можете сказати, що це йде на крок назад у додатку

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.