72

我正在使用推荐的向上导航方法,我的代码如下所示:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent h = new Intent(ShowDetailsActivity.this, MainActivity.class);
            h.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(h);
            return true;
        default: return super.onOptionsItemSelected(item);
    }
}

这是用例:

  1. 我启动我的应用程序“MainActivity”
  2. 我单击一个按钮转到“ShowDetailsActivity”
  3. 我点击 UP ActionBar 导航

问题是在我单击 UP 后,MainActivity 再次访问其 onCreate() 方法并丢失所有状态,而不是像我刚刚从 ShowDetailsActivity 调用“finish()”那样从典型的 onResume() 开始。为什么?这是它总是如何工作的吗?这是 Android 重新创建使用“向上”导航方法导航到的所有活动的预期行为?如果我点击后退按钮,我会得到预期的 onResume 生命周期。

如果不存在 Android“正确”的解决方案,这是我的解决方案:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent upIntent = new Intent(this, MainActivity.class);
            if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
                NavUtils.navigateUpTo(this, upIntent);
                finish();
            } else {
                finish();
            }
            return true;
        default: return super.onOptionsItemSelected(item);
    }
}
4

6 回答 6

93

将以下内容添加到清单文件中的父活动

android:launchMode="singleTop"

关于这个答案

于 2014-02-14T12:08:07.997 回答
61

使用向上导航时重新创建活动的原因是,如果您未指定其他模式,则 android 为此使用标准启动模式。这意味着

“系统总是在目标任务中创建一个新的活动实例”

因此重新创建了活动(请参阅此处的文档)。

一种解决方案是将 MainActivity 的启动模式声明为

android:launchMode="singleTop"

AndroidManifest.xml
(应始终与 一起工作Intent.FLAG_ACTIVITY_CLEAR_TOP

或者你可以添加FLAG_ACTIVITY_SINGLE_TOP到你的意图标志,告诉活动,它不应该被重新创建,如果它在后台堆栈上,例如

Intent h = NavUtils.getParentActivityIntent(this); 
h.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
NavUtils.navigateUpTo(this, h);
于 2014-01-07T15:15:34.420 回答
12

这段代码对我有用:

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    // This activity is NOT part of this app's task, so create a new task
    // when navigating up, with a synthesized back stack.
    TaskStackBuilder.create(this)
        // Add all of this activity's parents to the back stack
        .addNextIntentWithParentStack(upIntent)
        // Navigate up to the closest parent
        .startActivities();
} else {
    // This activity is part of this app's task, so simply
    // navigate up to the logical parent activity.
    upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    NavUtils.navigateUpTo(this, upIntent);
}

return true;

不需要完成()调用。

于 2013-08-26T06:49:44.740 回答
3

从 Android 4.1(API 级别 16)开始,您可以通过在元素中指定 android:parentActivityName 属性来声明每个活动的逻辑父级。如果您的应用支持 Android 4.0 及更低版本,请在您的应用中包含支持库并在 . 然后将父活动指定为 android.support.PARENT_ACTIVITY 的值,匹配 android:parentActivityName 属性。

<application ... >
...
<!-- The main/home activity (it has no parent activity) -->
<activity
    android:name="com.example.myfirstapp.MainActivity" ...>
    ...
</activity>
<!-- A child of the main activity -->
<activity
    android:name="com.example.myfirstapp.DisplayMessageActivity"
    android:label="@string/title_activity_display_message"
    android:parentActivityName="com.example.myfirstapp.MainActivity" >
    <!-- Parent activity meta-data to support 4.0 and lower -->
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.myfirstapp.MainActivity" />
</activity>

如果父activity有launch mode,或者upintent包含FLAG_ACTIVITY_CLEAR_TOP,父activity被带到栈顶,并通过其onNewIntent()方法接收intent。

<activity
        android:launchMode="singleTop"
        android:name="com.example.myfirstapp.MainActivity">

    </activity>

在上述代码“SingleTop”中,还可以创建“singleTop”活动的新实例来处理新意图。但是,如果目标任务在其堆栈顶部已经有活动的现有实例,则该实例将接收新意图(在 onNewIntent() 调用中);未创建新实例。

有关详细文档,请单击此处

要在用户按下应用程序图标时向上导航,您可以使用 NavUtils 类的静态方法 navigateUpFromSameTask()。 为此,请阅读上面链接中给出的文档。

于 2015-06-14T07:43:43.907 回答
1

对我有用的(我也认为最干净的)是将活动重新排序到前面。如果堆栈中不存在它,它将在您“导航”时创建。

Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(upIntent);
finish();
return true;
于 2014-10-13T04:47:35.697 回答
1

您只需要返回,而不是再次创建活动。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}
于 2015-05-23T16:21:00.450 回答