184

我的 android 应用程序中有 2 个活动(A 和 B),我使用意图从活动 A 到活动 B。启用了 parent_activity 的使用:

 <activity
        android:name=".B"
        android:label="B" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.app_name.A" />
  </activity>

我还使用了一个提供向上按钮的主题。

因此,在我调用活动 BI 后,可以使用向上按钮返回活动 A。问题是应用程序似乎再次调用活动 A 的onCreate()函数,这不是我需要的行为。我需要活动 A 看起来与调用活动 B 之前的外观相同。

有没有办法做到这一点?

编辑

我没有编写任何代码来从活动 A 启动活动 B。我认为它是由 Eclipse 自动生成的。

B类看起来像:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}


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

15 回答 15

345

launchMode您在 Android 清单中使用标准声明了活动 A。根据文档,这意味着以下内容:

系统总是在目标任务中创建一个新的活动实例并将意图路由到它。

onCreate因此,即使任务堆栈被正确处理,系统也被迫重新创建活动A(即调用)。

要解决此问题,您需要更改清单,将以下属性添加到 A 活动声明:

android:launchMode="singleTop"

注意:只有当您完全确定要终止的活动 B 实例位于活动 A 的实例之上时,调用finish()(如之前的解决方案所建议的那样)才有效。在更复杂的工作流中(例如,从通知启动活动 B)情况可能并非如此,您必须从 B 正确启动活动 A。

于 2013-04-10T18:43:43.667 回答
83

更新答案:向上导航设计

您必须声明哪个活动是每个活动的适当父项。这样做允许系统促进导航模式,例如向上,因为系统可以从清单文件中确定逻辑父活动。

因此,您必须在标签 Activity 中使用属性声明您的父 Activity

android:parentActivityName

像,

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

以这种方式声明的父活动,您可以向上导航到适当的父活动,如下所示,

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

因此,当您调用NavUtils.navigateUpFromSameTask(this);此方法时,它会完成当前活动并启动(或恢复)适当的父活动。如果目标父活动在任务的后台堆栈中,则按照FLAG_ACTIVITY_CLEAR_TOP.

要显示向上按钮,您必须声明setDisplayHomeAsUpEnabled():

@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

旧答案:(没有向上导航,默认返回导航)

仅当您从 Activity B 再次启动 Activity A 时才会发生这种情况。

使用startActivity().

而不是从 Activity A 开始 Activity B 使用并在 Activity A 中startActivityForResult()覆盖。onActivtyResult()

现在在活动 B 中只需调用finish()按钮向上。因此,现在您在onActivityResult()没有再次创建活动 A 的情况下定向到活动 A..

于 2012-09-05T07:00:39.633 回答
23

我的设置几乎相同,导致相同的不良行为。对我来说,这很有效:将以下属性添加到Manifest.xml我的应用程序中的活动 A 中:

android:launchMode="singleTask"

有关更多说明,请参阅本文

于 2013-03-17T10:29:09.540 回答
19

虽然是一个老问题,但这是另一个(恕我直言,最干净和最好的)解决方案,因为我从Widget深层链接了Activity B ,所以以前的所有答案都对我不起作用。

public void navigateUp() {
final Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent) || isTaskRoot()) {
    Log.v(logTag, "Recreate back stack");
        TaskStackBuilder.create(this).addNextIntentWithParentStack(upIntent).startActivities();
  } else {
    NavUtils.navigateUpTo(this, upIntent);
  }
}

[ https://stackoverflow.com/a/31350642/570168 ]

但也请参阅:https ://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android

于 2016-02-13T16:13:12.153 回答
7

实现此目的的更好方法是使用两件事:调用:

NavUtils.navigateUpFromSameTask(this);

现在,为了让它工作,你需要让你的清单文件声明活动 A 有一个父活动 B。父活动不需要任何东西。在版本 4 及更高版本中,您无需额外努力即可获得一个漂亮的后退箭头(这可以在较低版本上完成,只需少量代码,我将放在下面)您可以在 manifest->application 选项卡中设置此数据在 GUI 中(向下滚动到父活动名称,然后手动输入)

支持节点:

如果您希望支持低于版本 4 的版本,则还需要包含元数据。右键单击活动,添加->元数据,名称 =android.support.PARENT_ACTIVITY 和值 = your.full.activity.name

在较低版本中获得漂亮的箭头:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

请注意,您需要支持库版本 7 才能使这一切正常工作,但这是非常值得的!

于 2013-09-22T14:50:45.800 回答
5

对我有用的是添加:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }

TheRelevantActivity.java现在它按预期工作

是的,别忘了添加:

getSupportActionbar.setDisplayHomeAsUpEnabled(true);onCreate()方法中

于 2017-07-28T10:22:21.300 回答
4

我试过android:launchMode="singleTask"了,但没有帮助。为我工作android:launchMode="singleInstance"

于 2015-03-04T08:20:04.490 回答
4

添加到@LorenCK的答案,改变

NavUtils.navigateUpFromSameTask(this);

如果您的活动可以从另一个活动启动,并且这可以成为其他应用程序启动的任务的一部分,请转到下面的代码

Intent upIntent = NavUtils.getParentActivityIntent(this);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(upIntent)
            .startActivities();
} else {
    NavUtils.navigateUpTo(this, upIntent);
}

这将启动一个新任务并启动您的 Activity 的父 Activity,您可以在 Manifest 中定义如下 Min SDK version <= 15

<meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.app_name.A" />

或使用parentActivityName> 15

于 2016-03-22T19:13:57.123 回答
3

我在使用带有错误父活动名称的 android 5.0 时遇到了类似的问题

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

我从父活动名称中删除了 com.example.myfirstapp 并且它工作正常

于 2014-10-29T16:27:51.287 回答
3

在 Java 类中:-

    toolbar = (Toolbar) findViewById(R.id.apptool_bar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setTitle("Snapdeal");

    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

在清单中:-

<activity
            android:name=".SubActivity"
            android:label="@string/title_activity_sub"
            android:theme="@style/AppTheme" >
            <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"></meta-data>
    </activity>

它会帮助你

于 2016-05-28T07:39:41.103 回答
2

使用属性添加到您的活动清单信息

android:launchMode="singleTask"

对我来说效果很好

于 2014-03-08T06:11:18.943 回答
1

试试这个:

Intent intent;
@Override
public void onCreate(Bundle savedInstanceState) {
    intent = getIntent();   
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_b, menu);
    return true;
}  

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpTo(this,intent);
            return true;
    }
    return super.onOptionsItemSelected(item);
}
于 2013-09-29T05:43:05.283 回答
1
    @Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
    case android.R.id.home:
        finish();
        return true;
}
return super.onOptionsItemSelected(item);

像背压机

于 2017-08-05T10:54:15.847 回答
0

进入我的清单并添加android:launchMode="singleTop"到活动中为我做了诀窍。

这特别解决了我的问题,因为我不希望 Android 在点击Up工具栏中的按钮后创建上一个活动的新实例——我想在向上导航层次结构时使用上一个活动的现有实例。

参考:android:launchMode

于 2016-02-18T23:47:16.877 回答
0

试试这个解决方案,使用 NavUtils.navigateUpFromSameTask(this); 在子活动中: https ://stackoverflow.com/a/49980835/7308789

于 2018-04-23T12:29:37.707 回答