174

I'm developing android applications for a while, and followed a lot of posts about activity life cycle, and application's life cycle.

I know Activity.finish() method calls somewhere in the way to Activity.onDestroy(), and also removing the activity from stack, and I guess it somehow points to operating system and garbage collector that he can "do his trick" and free the memory when it find it a good time doing so....

I came to this post - Is quitting an application frowned upon? and read Mark Murphy's answer.

It made me a bit confused about what exactly the finish() method actually does.

Is there a chance I'll call finish() and onDestroy() won't be called?

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Tal Kanel
  • 10,475
  • 10
  • 60
  • 98
  • Related thread - [How does Activity.finish() work in Android?](https://stackoverflow.com/q/2590947/465053) – RBT Aug 23 '18 at 23:57

13 Answers13

194

When calling finish() on an activity, the method onDestroy() is executed. This method can do things like:

  1. Dismiss any dialogs the activity was managing.
  2. Close any cursors the activity was managing.
  3. Close any open search dialog

Also, onDestroy() isn't a destructor. It doesn't actually destroy the object. It's just a method that's called based on a certain state. So your instance is still alive and very well* after the superclass's onDestroy() runs and returns.Android keeps processes around in case the user wants to restart the app, this makes the startup phase faster. The process will not be doing anything and if memory needs to be reclaimed, the process will be killed

Software Dev
  • 5,368
  • 5
  • 22
  • 45
K_Anas
  • 31,226
  • 9
  • 68
  • 81
  • 7
    so finish() method only triggering call to onDestroy() and that's it? – Tal Kanel Jun 02 '12 at 14:47
  • yes it triggers onDestroy() that will destroy the activity respecting the concept of an activity is Life cycle – K_Anas Jun 02 '12 at 15:21
  • 1
    So after finish(), all the variables in this activity will be destroyed, right? When I come back to this activity once again, they will be re-declared or initialized, right? – Sibbs Gambling Jul 16 '13 at 02:24
  • 9
    Yes, if you come back to the Activity onCreate() will be called. – Luis Pena Feb 15 '14 at 17:48
  • 9
    Does finish() also call onPause() and onStop() ? – sr09 Jul 11 '14 at 01:46
  • As I tested, finish() doesn't call onPause() and onStop(). Pls correct me if you think it is not correct. – Sam003 Apr 01 '15 at 19:55
  • 42
    I tested again, and found that onPause(), onStop() and onDestroy() will all be called in order after you call finish(). – Sam003 Jul 13 '15 at 23:55
  • onPause() and onStop() will always be called before onDestroy() - them's the rules of Android lifecycle – Laurent Aug 09 '15 at 00:24
  • 5
    @Laurent onPause() and onStop() are not always called. See my observation in below answer – Prakash Sep 10 '15 at 17:40
  • 1
    Maybe this is obvious to some, but isn't to all: `finish()` will also, after closing the current Activity, reopen the previous activity on the back stack (if there is one). – LarsH Jul 29 '17 at 04:59
  • 1
    I called finish() from the onCreate(), onPause() and onStop() didn't get called, onDestroy() got called. Just like @Prakash mentioned. – Sreekanth Karumanaghat Dec 18 '19 at 08:14
93

My 2 cents on @K_Anas answer. I performed a simple test on finish() method. Listed important callback methods in activity life cycle

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

What I mean to say is that counterparts of the methods along with any methods in between are called when finish() is executed.

eg:

 onCreate() counter part is onDestroy()
 onStart() counter part is onStop()
 onPause() counter part is onResume()
Prakash
  • 7,794
  • 4
  • 48
  • 44
45

Also notice if you call finish() after an intent you can't go back to the previous activity with the "back" button

startActivity(intent);
finish();
Dan Wears Prada
  • 734
  • 6
  • 11
  • 1
    This is exactly the info I needed, since I have an activity which only connects to google drive, then it does its checks and it moves on to the main activity (or to the Settings activity if there is an error), so the user shouldn't be able to go back. – Francesco Marchetti-Stasi Sep 03 '18 at 16:13
  • 1
    @Francesco Marchetti-Stasi In your case it would be better to override onBackPressed() and not calling super.onBackPressed() in it if the user shouldn't go back. – Paul Nov 04 '19 at 18:41
13

onDestroy() is meant for final cleanup - freeing up resources that you can on your own,closing open connections,readers,writers,etc. If you don't override it, the system does what it has to.

on the other hand, finish() just lets the system know that the programmer wants the current Activity to be finished. And hence, it calls up onDestroy() after that.

Something to note:

it isn't necessary that only a call to finish() triggers a call to onDestroy(). No. As we know, the android system is free to kill activities if it feels that there are resources needed by the current Activity that are needed to be freed.

Kazekage Gaara
  • 14,972
  • 14
  • 61
  • 108
  • 1
    you wrote that finish() let the system know the activity need to be finishd. so it's like saying "do x = tell the system to do x". seconds thing: from your answer it sounds like there is a way I'll call finish(), and the system will decide not to call onDestroy()? is it possible? – Tal Kanel Jun 01 '12 at 09:27
  • You got the first part right. Calling `finish()` is telling the system to finish the `Activity`. the "x" part in your do statement is "to finish(destroy) the `Activity`". The second part is wrong. Actually, I missed a word there. I have edited the answer. `onDestroy()` is not just triggered by `finish()`, the system can call it on it's own as well. – Kazekage Gaara Jun 01 '12 at 09:31
  • 1
    I've just read your addition to the answer. for now I've up-voted the answer cause I've found your explanation interesting, but I would like to see if other's would have something else to say about it before marking it as "answerd". thanks for now :) – Tal Kanel Jun 01 '12 at 09:33
  • So after finish(), all the variables in this activity will be destroyed, right? When I come back to this activity once again, they will be re-declared or initialized, right? – Sibbs Gambling Jul 16 '13 at 02:24
  • 3
    Note: if the system kills the process, onDestroy may not be called. http://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29 – Kevin Lee Mar 14 '16 at 17:21
  • "As we know, the android system is free to kill activities if it feels that there are resources needed by the current Activity that are needed to be freed." This is an incorrect sentence. Android only kills the whole process app if there is a problem: https://stackoverflow.com/questions/11616575/android-not-killing-activities-from-stack-when-memory-is-low – Gaket Nov 05 '17 at 09:33
11

In addition to @rommex answer above, I have also noticed that finish() does queue the destruction of the Activity and that it depends on Activity priority.

If I call finish() after onPause(), I see onStop(), and onDestroy() immediately called.

If I call finish() after onStop(), I don't see onDestroy() until 5 minutes later.

From my observation, it looks like finish is queued up and when I looked at the adb shell dumpsys activity activities it was set to finishing=true, but since it is no longer in the foreground, it wasn't prioritized for destruction.

In summary, onDestroy() is never guaranteed to be called, but even in the case it is called, it could be delayed.

Brandon Lim
  • 271
  • 2
  • 12
9

Finish() method will destroy the current activity. You can use this method in cases when you dont want this activity to load again and again when the user presses back button. Basically it clears the activity from the.current stack.

Udit Kapahi
  • 2,277
  • 1
  • 27
  • 25
6

Various answers and notes are claiming that finish() can skip onPause() and onStop() and directly execute onDestroy(). To be fair, the Android documentation on this (http://developer.android.com/reference/android/app/Activity.html) notes "Activity is finishing or being destroyed by the system" which is pretty ambiguous but might suggest that finish() can jump to onDestroy().

The JavaDoc on finish() is similarly disappointing (http://developer.android.com/reference/android/app/Activity.html#finish()) and does not actually note what method(s) are called in response to finish().

So I wrote this mini-app below which logs each state upon entry. It includes a button which calls finish() -- so you can see the logs of which methods get fired. This experiment would suggested that finish() does indeed also call onPause() and onStop(). Here is the output I get:

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
  • 944
  • 2
  • 8
  • 21
4

@user3282164 According to the Activity life-cycle it should go through onPause() -> onStop() -> onDestroy() upon calling finish().

The diagram does not show any straight path from [Activity Running] to [onDestroy()] caused by the system.

onStop() doc says "Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called."

Ralf
  • 14,655
  • 9
  • 48
  • 58
Meryan
  • 1,285
  • 12
  • 25
  • **NOT EXACTLY** see: http://stackoverflow.com/questions/12655898/finish-and-the-activity-lifecycle/30227647#30227647 – ceph3us May 14 '15 at 01:10
4

calling finish in onCreate() will not call onDestroy() directly as @prakash said. The finish() operation will not even begin until you return control to Android.

Calling finish() in onCreate(): onCreate() -> onStart() -> onResume(). If user exit the app will call -> onPause() -> onStop() -> onDestroy()

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

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

For further reference check look at this oncreate continuous after finish & about finish()

Community
  • 1
  • 1
anand krish
  • 4,281
  • 4
  • 44
  • 47
3

My study shows that finish() method actually places some destruction operations in the queue, but the Activity is not destroyed immediately. The destruction is scheduled though.

For example, if you place finish() in onActivityResult() callback, while onResume() has yet to run, then first onResume() will be executed, and only after that onStop() and onDestroy() are called.

NOTE: onDestroy() may not be called at all, as stated on the documentation.

ebarrenechea
  • 3,775
  • 1
  • 31
  • 37
rommex
  • 763
  • 1
  • 8
  • 21
1

It seems that the only correct answer here so far has been given by romnex: "onDestroy() may not be called at all". Even though in practice, in almost all cases it will, there is no guarantee: The documentation on finish() only promises that the result of the activity is propagated back to the caller, but nothing more. Moreover, the lifecycle documentation clarifies that the activity is killable by the OS as soon as onStop() finishes (or even earlier on older devices), which, even though unlikely and therefore rare to observe in a simple test, might mean that the activity might be killed while or even before onDestroy() is executed.

So if you want to make sure some work is done when you call finish(), you cannot put it in onDestroy(), but will need to do in the same place where you call finish(), right before actually calling it.

urps
  • 366
  • 1
  • 4
  • 13
1

Roomex said it correctly!

What happened to me was that I was working on an app that requires me to use Bluetooth listener Class. One Fragment from the homepage called an activity that was also using BluetoothListner class. I used the startActivityForResult() method to get acknowledgment. And the problem was after getting the acknowledgment of the fragment when tries to listen to the Bluetooth port the activities channel was still active. Even though I specifically closed it onDestroy() method. I spent days but couldn't get how to stop.

I figured if I don't use startAcivityForResult() and just use startActivity() with and without the finish() method called that could potentially solve the issue. Of course, if I do call finish() inside fragment then from the activity will have to recall the MainActivity with the navigation view and point to the fragment. this way it will potentially create a brand new instance of the MainActivity. Or without using finish() while calling Activity the onDestroy() method will invoke for the activity and the fragment's onResume() method will be called once we return to it.

Faiz Alam
  • 11
  • 2
-5

finish () just sends back to the previous activity in android, or may be you can say that it is going one step back in application

kapil
  • 19