Soon Santos
Soon Santos

Reputation: 2219

onStop delays to be called when restarting activity

When restarting an Activity, onStop() from previous activity delays too much to be called.

I am using this code to restart my activity PlayerActivity.java

Intent playerIntent = getIntent();
playerIntent.putExtra(Constants.VIDEO_ID, videoId);
playerIntent.putExtra(Constants.CATEGORY_ID, categoryId);
playerIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(playerIntent);

Let's call PreviousPlayerActivity and NewPlayerActivity, the activity that was before and the new activity. (remembering that they are the same PlayerActivity).

Sequence

When restarting the app follows this flow in the activity-lifecycle.

PreviousPlayerActivity onPause() --> 
NewPlayerActivity onCreate() --> 
NewPlayerActivity onStart() --> 
NewPlayerActivity onResume() --> 
NewPlayerActivity performs a heavy operation --> 
PreviousPlayerActivity onStop() --> 
PreviousPlayerActivity onDestroy()

What I need

I need PreviousPlayerActivity to be completed destroyed before NewPlayerActivity starts. However, onStop() is just called after the heavy operation, so it delays around 10 seconds to be called.

What I tried

If I use recreate() method it does destroy PreviousPlayerActivity before calling NewPreviousActivity, but by calling recreate() I can not putExtras into the new activity instance.

Questions

  1. How to completely destroy PreviousActivity when restarting an activity?
  2. Is there a way to putExtras while using recreate()?

Upvotes: 1

Views: 1452

Answers (2)

Son Truong
Son Truong

Reputation: 14173

In Activity Lifecycle from Android Developer guide.

Coordinating activities

When one activity starts another, they both experience lifecycle transitions. The first activity stops operating and enters the Paused or Stopped state, while the other activity is created. In case these activities share data saved to disc or elsewhere, it's important to understand that the first activity is not completely stopped before the second one is created. Rather, the process of starting the second one overlaps with the process of stopping the first one.

The order of lifecycle callbacks is well defined, particularly when the two activities are in the same process (app) and one is starting the other. Here's the order of operations that occur when Activity A starts Activity B:

  1. Activity A's onPause() method executes.
  2. Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
  3. Then, if Activity A is no longer visible on screen, its onStop() method executes.

This predictable sequence of lifecycle callbacks allows you to manage the transition of information from one activity to another.

So the behavior that you describe is expected or predictable.

Back to your questions.

1.How to completely destroy PreviousActivity when restarting an activity?

  • Using recreate API, the limitation is it only works from API 11 or above

2.Is there a way to putExtras while using recreate()?

recreate

public void recreate ()

Cause this Activity to be recreated with a new instance. This results in essentially the same flow as when the Activity is created due to a configuration change -- the current instance will go through its lifecycle to onDestroy() and a new instance then created after it.

Because the activity will be recreated so onSaveInstanceState and onRestoreInstanceState will be called as well. As you can guess the idea is save data in onSaveInstanceState and retrieve in onRestoreInstanceState or onCreate.

Step 1: Save data in onSaveInstanceState

// The key for saving and retrieving isActivityRecreated field.
private static final String KEY_IS_ACTIVITY_RECREATED = "KEY_IS_ACTIVITY_RECREATED";

/** true if this activity is recreated. */
private boolean isActivityRecreated = false;

// Call this method when you want to recreate this activity.
private void recreateActivity() {
    isActivityRecreated = true;
    recreate();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(KEY_IS_ACTIVITY_RECREATED, isActivityRecreated);
    outState.putInt(Constants.VIDEO_ID, videoId);
    outState.putInt(Constants.CATEGORY_ID, categoryId);
}

Step 2: Retrieve the data in onRestoreInstanceState or onCreate

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        isActivityRecreated = savedInstanceState.getBoolean(KEY_IS_ACTIVITY_RECREATED);
        if (isActivityRecreated) {
            // This activity has been recreated.
            // Reset the flag
            isActivityRecreated = false;

            // Write your code when this activity recreated.
            int videoId = savedInstanceState.getInt(Constants.VIDEO_ID);
            int categoryId = savedInstanceState.getInt(Constants.CATEGORY_ID);
            ...   
        }
    }
}

Upvotes: 4

PushpikaWan
PushpikaWan

Reputation: 2545

You can do it simply by setting a noHistory flag as true in AndroidManifest.xml file. I think you don't need to keep that activity state when minimizing according to your requirement.

<activity
            android:name=".PlayerActivity"
            android:noHistory="true" />

Upvotes: 0

Related Questions