Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

activity finishes itself but onDestroy() call for this activity happen so late

I found a bug in our code that we are launching the activity(let's call this as SCREEN_ACTIVITY) by

Intent intent = new Intent(SharedIntents.INTENT_SCREEN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);

Android documentation : When using FLAG_ACTIVITY_NEW_TASK, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in.

So everything works fine in most of the case.

That screen activity will call finish() when user click something. Also this screen activity will get launch or create by incoming event from the service.

6053 I/ScreenActivity(15395): onCreate
6682 E/ScreenActivity(15395): finish() Activity
6832 I/ScreenActivity(15395): onDestroy

7284 I/ScreenActivity(15395): onCreate
7911 E/ScreenActivity(15395): finish() Activity
8063 I/ScreenActivity(15395): onDestroy

10555 I/ScreenActivity(15395): onCreate
13413 E/ScreenActivity(15395): finish() Activity
13701 I/ScreenActivity(15395): onCreate
13799 I/ScreenActivity(15395): onDestroy

The last one is the issue. ScreenActivity is created and then call finish() itself. But the problem is that onDestroy is being called very late. Before that there is incoming event from the server and calling startActivity() trigger a new ScreenAcitivty onCreate(). The problem is that ScreenManager class keeps flags for that activity created and destroyed.

The flag is set when onCreate() callback and onDestroy() callback. So for line 10555 and 13701 the ScreenManager set createFlag = true. for line 13799 set createFlag = false. The event comes after line 13799 will assume that the activity is not created and events are not notified to the activity.

Hope my description for the issue is clear to you. Is this kind of scenario onStop() and onDestroy() call so late after calling finish() is expected to happen? If yes, i have to think about the solution. If not, then is there any places to modify?

Thanks a lot.

like image 860
rodent_la Avatar asked Nov 30 '22 22:11

rodent_la


1 Answers

onDestroy() may or may not be called. You cannot rely on it being called all the time. From the docs:

Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.

If you need to know that your Activity is finishing, a reliable way to know if it is finishing is the isFinishing() method. You can call it in onPause() to find out if this pause will eventually lead to this Activity being destroyed:

@Override
protected void onPause() {
    super.onPause();
    if (isFinishing()) {
        // Here  you can be sure the Activity will be destroyed eventually
    }
}
like image 197
Veneet Reddy Avatar answered Dec 04 '22 13:12

Veneet Reddy