23

I have a very simple app based on the Building Your First App tutorial. There are two activities: MainActivity invokes DisplayMessageActivity through startActivity().

When entering DisplayMessageActivity, I see:

MainActivity.onStop()

as expected, but when I press the back button to return to the parent MainActivity, I get:

MainActivity.onDestroy()
MainActivity.onCreate(null)
MainActivity.onStart()

The activity always gets destroyed for this very simple application. But according to the documentation (second bullet point), the typical behavior is for the activity to be stopped and restarted in such cases.

Also, onDestroy() does not happen when first starting the child activity, but only once back button is clicked.

Two questions:

  1. Is there a way to prevent parent from being destroyed in the common case?
  2. Why is null being passed to onCreate() here? This prevents me from preserving state through onSaveInstanceState().

Note that I've verified that Settings -> Developer Options -> Apps -> Don't keep activities is unchecked.

Edit:

Here is how the child activity is linked to parent:

    <activity
        android:name="com.example.helloworld.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.helloworld.MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.helloworld.MainActivity" />
    </activity>

Tracing through DisplayMessageActivity.onOptionsItemSelected(), I can see that it's calling Activity.onNavigateUp().

mtoossi
  • 937
  • 8
  • 14
  • Did you implement `onSaveInstanceState()` in `MainActivity`? Did you rotate your phone to landscape from portrait or vice versa while on `DisplayMessageActivity`? – Greg Giacovelli Dec 28 '13 at 20:30
  • I have tried implementing `onSaveInstanceState()` in `MainActivity`. It helped when screen was being rotated while on `MainActivity`. It, however, was useless in the situation mentioned above since `onCreate()` is passed a `null` bundle. – mtoossi Dec 28 '13 at 20:33
  • To your second question, no I didn't rotate the phone while on `DisplayMessageActivity`. I have tried this several times with this and one other application I've written and the parent activity gets destroyed and created with `null` bundle every time. – mtoossi Dec 28 '13 at 20:34
  • Does DisplayMessageActivity use a large amount of resources? or does MainActivity for that matter? It's perfectly normal to kill these activities, but the saveInstanceState should be honored unless DisplayMessageActivity just starts a new MainActivity rather than just finishing and popping off the backstack – Greg Giacovelli Dec 28 '13 at 20:36
  • `DisplayMessageActivity` only has a `TextView` just like the tutorial I linked. I return to `MainActivity` by clicking the back button on the action bar. – mtoossi Dec 28 '13 at 20:41
  • @GregGiacovelli: I've added some more details above on how the child activity is linked to parent. From your reply, it really looks like a new `MainActivity` is being created, so maybe something is wrong with the way I link to parent? – mtoossi Dec 28 '13 at 20:53

2 Answers2

30

Thanks to Greg Giacovelli's comments, I found the answer here. The solution was to set android:launchMode="singleTop" to the parent activity.

I still can't understand why such basic information is so unknown and hard to find!

NoHarmDan
  • 492
  • 5
  • 16
mtoossi
  • 937
  • 8
  • 14
  • 2
    There is a lot of information, it's like trying to find a needle in a sea of needles! – Steve M Dec 28 '13 at 21:21
  • +1 WOW! Finally found it after two days of headache! I was trying to look how it would be possible to restore my maps in the MainAcvitiy, after a SettingsActivity was being called. No more needed! I knew there should be a way out of it! Thanks! – Eduardo Oct 28 '15 at 16:27
  • 1
    `android:launchMode="singleTop"` must be set on the main activity. I initially only set it on the activity started from the main activity which obviously didn't help. – nibarius Aug 25 '17 at 18:59
  • i was using SingleTask and had this problem. why did I have it with singleTask and what makes difference? – Emil Nov 07 '17 at 23:54
  • Unlike the answer by @Kislingk, this actually works. – NoHarmDan Nov 22 '19 at 13:11
0

Adding launchMode in Manifest changes launch mode every time, even it is not launched by child activity. There are other ways to launch existed instance.

1.override onOptionsItemSelected(item: MenuItem)

override fun onOptionsItemSelected(item: MenuItem): Boolean {
   return when (item.itemId) {
        android.R.id.home -> {
            // Respond to the action bar's Up/Home button
            val upIntent: Intent? = NavUtils.getParentActivityIntent(this)
            when {
                upIntent == null -> throw IllegalStateException("No Parent Activity Intent")
                else -> {
                    //add launch flag here
                    upIntent.flags=Intent.FLAG_ACTIVITY_CLEAR_TOP
                    NavUtils.navigateUpTo(this, upIntent)
                }
            }
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}
  1. 2nd solution looks like a bug. Set "android:parentActivityName" to activity which is not existed in current task stack. Android will behavior like "BACK" button. It launches the top instance instead of launching parent activity. Document mentions "NavUtils.shouldUpRecreateTask" can recognize if parent activity existed in current task. But it doesn't work in my test. Navigate up with a new back stack
Kislingk
  • 1,427
  • 14
  • 23