activity not calling onDestroy() after finish()

10,031

Solution 1

an activity is not finished / destroyed on back pressed.

Use

 @Override
    public void onBackPressed()
    {
        finish();
    }

Solution 2

Since I can not comment I will write here.

I am not 100% sure if I followed you but right near the end you mention that

After THREE is destroyed (a second time), TWO opens as expected.

What do you mean by that since if I followed you correctly you said that you open TWO with a button in ONE and THREE with a button in TWO. So how can TWO open as expected, or you mean then it goes to onDestroy() when you exit it?

What I am aiming at is that perhaps you open more instances of the same activity, as is mentioned in the here if you take a look at Figure 3.

Share:
10,031
nak5ive
Author by

nak5ive

i do things

Updated on June 05, 2022

Comments

  • nak5ive
    nak5ive about 2 years

    I have three activities, let's call them ONE, TWO and THREE. From activity ONE, a button press starts activity TWO. From activity TWO, a button press starts activity THREE.

    Simple enough.

    Now, activity THREE requires a bit of data accessible from the application (which may or may not be there). In THREE's onResume() method, a check is made for the data and the activity is finished if it doesn't exist, like so:

    @Override
    protected void onResume() {
        super.onResume();
    
        /* ... get data from app ... */
    
        if (data == null) {
            Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
    
        /* ... other logic ... */
    }
    

    When data == null, THREE finishes, destroys and returns to TWO. All is well. Now in TWO, pressing the back button calls finish() on TWO, but TWO never calls onDestroy(). The user is returned to ONE just fine, but any subsequent intent to go back to TWO does not work and no errors are thrown. TWO is left in a state where it has been finished (and paused), but never destroyed, and as a result cannot resume.

    So, why is THREE important in this case? If I remove the finish() call in the code block above, and rely on a "natural" finishing of THREE (by using the back button), when the user gets back to ONE, TWO has been destroyed correctly.

    OK here's where it gets really confusing...

    Leaving the finish() call in place, I can alleviate the hangup by launching THREE directly from ONE, then "naturally" finish it (back button). After THREE is destroyed (a second time), TWO opens as expected.

    Everything I've read has said I should be ok calling finish() within onResume() for an activity. But in this case, it is leaving something in a bad state and prevents me from destroying the calling activity down the line.

    Ideas? or did I turn your brains inside out?

    EDIT:

    Further exploration uncovered this gem...

    Surrounding the finish() call in THREE with a postDelay() handler of around 500 millis will allow TWO to close as expected. Like this:

    @Override
    protected void onResume() {
        super.onResume();
    
        /* ... get data from app ... */
    
        if (data == null) {
            Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
            Handler h = new Handler();
            h.postDelayed(new Runnable() {
                @Override
                public void run() {
                    finish();
                }
            }, 500);
            return;
        }
    
        /* ... other logic ... */
    }
    

    Not exactly my idea of a fix...