ActionBar向上导航重新创建父活动,而不是onResume


70

我对上行导航使用推荐的方法,我的代码如下所示:

@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);
    }
}

Answers:



60

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

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

从而重新创建了活动(请参阅此处的docu )。

一种解决方案是将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);

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;

无需finish()调用。


谢谢!这确实解决我的问题,但我仍然不知道为什么会出现这种情况,因为我没有在父活动调用finish()..

4
可能是您的主要活动在AndroidManifest.xml中没有此选项android:launchMode =“ singleTop”。有时android创建新的活动,即使它已经在顶部。
维克多·德尼索夫

设置android:parentActivityName,使用默认的后续行动或NavUtils.navigateUpFromSameTask(this);使用intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)了一些活动使得它为我工作。谢谢@VictorDenisov。
FMCorz

当我添加此行upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 有效。
kml_ckr

1
我只是用姜饼测试了可接受的答案,不幸的是它不起作用。
AlexBrand

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>

如果父活动具有启动模式,或者向上意图包含FLAG_ACTIVITY_CLEAR_TOP,则将父活动带到堆栈的顶部,并通过其onNewIntent()方法接收该意图。

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

    </activity>

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

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

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


1

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

Intent upIntent = NavUtils.getParentActivityIntent(this);
upIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(upIntent);
finish();
return true;

0

您只需要返回即可,而无需再次创建活动。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

6
但这是错误的。请参阅developer.android.com/training/design-navigation/…docu。向上导航应始终转到“向上活动”。例如,如果您从另一个应用程序开始活动,并且用户向上按,则应转到父级。通过您的实施,用户可以返回到旧应用。
StefMa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.