Android 如何正确返回父活动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12276027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:17:47  来源:igfitidea点击:

How can I return to a parent activity correctly?

androidandroid-intentandroid-activityparent

提问by ashiaka

I have 2 activities (A and B) in my android application and I use an intent to get from activity A to activity B. The use of parent_activity is enabled:

我的 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>

I also use a theme which provides an UP-button.

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

So after I called activity B I can use the UP-button to get back to the activity A. The problem is that the application seems to call the onCreate()-function of activity A again and this is not the behaviour I need. I need activity A to look the same way like it looked before I called activity B.

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

Is there a way to achieve this?

有没有办法实现这一目标?

Thanks in advance

提前致谢

EDIT:

编辑:

I didn't write any code to start activity B from activity A. I think it is autogenerated by eclipse.

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

Class B looks like:

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

回答by LorenzCK

You declared activity A with the standard launchModein the Android manifest. According to the documentation, that means the following:

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

The system always creates a new instance of the activity in the target task and routes the intent to it.

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

Therefore, the system is forced to recreate activity A (i.e. calling onCreate) even if the task stack is handled correctly.

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

To fix this problem you need to change the manifest, adding the following attribute to the A activity declaration:

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

android:launchMode="singleTop"

Note:calling finish()(as suggested as solution before) works onlywhen you are completely surethat the activity B instance you are terminating lives on top of an instance of activity A. In more complex workflows (for instance, launching activity B from a notification) this might not be the case and you have to correctly launch activity A from B.

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

回答by user370305

Updated Answer: Up Navigation Design

更新答案:向上导航设计

You have to declare which activity is the appropriate parent for each activity. Doing so allows the system to facilitate navigation patterns such as Up because the system can determine the logical parent activity from the manifest file.

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

So for that you have to declare your parent Activity in tag Activity with attribute

因此,为此您必须在带有属性的标签 Activity 中声明您的父 Activity

android:parentActivityName

android:parentActivityName

Like,

喜欢,

<!-- 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>

With the parent activity declared this way, you can navigate Up to the appropriate parent like below,

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

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

So When you call NavUtils.navigateUpFromSameTask(this);this method, it finishes the current activity and starts (or resumes) the appropriate parent activity. If the target parent activity is in the task's back stack, it is brought forward as defined by FLAG_ACTIVITY_CLEAR_TOP.

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

And to display Up button you have to declare setDisplayHomeAsUpEnabled():

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

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

Old Answer: (Without Up Navigation, default Back Navigation)

旧答案:(没有向上导航,默认后退导航)

It happen only if you are starting Activity A again from Activity B.

只有当您从活动 B 再次启动活动 A 时才会发生这种情况。

Using startActivity().

使用startActivity().

Instead of this from Activity A start Activity B using startActivityForResult()and override onActivtyResult()in Activity A.

而不是从活动 A 开始使用活动 BstartActivityForResult()onActivtyResult()在活动 A 中覆盖。

Now in Activity B just call finish()on button Up. So now you directed to Activity A's onActivityResult()without creating of Activity A again..

现在在活动 B 中只需调用finish()按钮向上。所以现在你定向到活动 AonActivityResult()而没有再次创建活动 A..

回答by androidnewbie

I had pretty much the same setup leading to the same unwanted behaviour. For me this worked: adding the following attribute to an activity A in the Manifest.xmlof my app:

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

android:launchMode="singleTask"

See this articlefor more explanation.

有关更多解释,请参阅此文章

回答by Tobias

Although an old question, here is another (imho the cleanest and best) solution as all the previous answeres didn't work for me since I deeplinked Activity Bfrom a Widget.

虽然是一个老问题,但这是另一个(恕我直言是最干净和最好的)解决方案,因为自从我从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://stackoverflow.com/a/31350642/570168]

But also see: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android

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

回答by donald

A better way to achieve this is by using two things: call:

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

NavUtils.navigateUpFromSameTask(this);

Now, in order for this to work, you need to have your manifest file state that activity A has a parent activity B. The parent activity doesn't need anything. In version 4 and above you will get a nice back arrow with no additional effort (this can be done on lower versions as well with a little code, I'll put it below) You can set this data in the manifest->application tab in the GUI (scroll down to the parent activity name, and put it by hand)

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

Support node:

支持节点:

if you wish to support version below version 4, you need to include metadata as well. right click on the activity, add->meta data, name =android.support.PARENT_ACTIVITY and value = your.full.activity.name

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

to get the nice arrow in lower versions as well:

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

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

please note you will need support library version 7 to get this all working, but it is well worth it!

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

回答by Hammad Nasir

What worked for me was adding:

对我有用的是添加:

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

to TheRelevantActivity.javaand now it is working as expected

TheRelevantActivity.java现在它正在按预期

and yeah don't forget to add:

是的,不要忘记添加:

getSupportActionbar.setDisplayHomeAsUpEnabled(true);in onCreate()method

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

回答by Sourabh

Adding to @LorenCK's answer, change

添加到@LorenCK 的答案,更改

NavUtils.navigateUpFromSameTask(this);

to the code below if your activity can be initiated from another activity and this can become part of task started by some other app

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

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

This will start a new task and start your Activity's parent Activity which you can define in Manifest like below of Min SDK version <= 15

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

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

Or using parentActivityNameif its > 15

或者使用parentActivityName如果其 > 15

回答by Pnemonic

I tried android:launchMode="singleTask", but it didn't help. Worked for me using android:launchMode="singleInstance"

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

回答by Patrick Bergthold

I had a similar problem using android 5.0 with a bad parent activity name

我在使用带有错误父活动名称的 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>

I removed the com.example.myfirstapp from the parent activity name and it worked properly

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

回答by Pravesh Kumar

Add to your activity manifest information with attribute

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

android:launchMode="singleTask"

is working well for me

对我来说效果很好