如何检测父 activity 是否在返回堆栈中并且可以在不创建新实例的情况下上升?

How to detect if a parent activity is in the back stack and can go up without creating a new instance?

我的系统有几个 ActivityActivity XActivity AActivity BActivity YActivity XA 的列表组成。如果我们点击 A,它将转到 Activity AActivity AB 的列表组成。如果我们点击 B,它将转到 Activity BActivity B 也将包含 B 的列表。因此,如果我们在 Activity B 上单击 B,它将转到 Activity B。可以这样结束堆栈:X -> A -> B -> B -> B -> B -> B。根据 Android 的正确导航,如果我们在 Activity B 上单击 Up,无论堆栈有多深,它都应该转到 Activity A。因此,前一个堆栈中的每个 B 都应该在 A 上结束。到目前为止,这很简单。我只需要将 Activity B 的父 class 设置为 Activity A.

问题是我可以从 Activity Y 转到 Activity B。如果我从 Activity Y 打开 Activity B,这个 Activity B 并不总是知道如何打开 Activity A 因为 B 的父级可以是另一个 BAB只认识他爸妈。问题是如何在不从 Activity B 创建新实例的情况下自动检测 Activity A 是否可达?这样,我就可以在 Activity B 上编写如下代码。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            if (canGoUpToActivityA()) { // this means this Activity B is opened from Activity A directly (A -> B) or indirectly (A -> B -> ... -> B), not from Activity Y
                NavUtils.navigateUpFromSameTask(this);
                return true;
            } else {
                Intent intent;

                if (TYPE_B.equals(mParent.getType())) {
                   intent = new Intent(this, ActivityB.class);
                } else {
                   intent = new Intent(this, ActivityA.class);
                }

                intent.putExtra(EXTRA_ITEM, mParent)
                startActivity(intent);                    

                return true;
            }
        default:
            return super.onOptionsItemSelected(item);
    }
}

编辑

如果有人因为认为解决方案就像 singleTopActivity A 一样简单而对我投反对票,那就意味着你们不理解我的问题。看我第一段的最后一句。从 Activity B 上升到 Activity A 没有任何问题,无论从 Activity A.

打开 Activity B 有多深

如果没有上面的onOptionsItemSelected,如果直接从Activity A打开Activity B,我可以从Activity B升到Activity A(A -> B)或间接 (A -> B -> ... -> B)。这不是我的问题。

当我从 Activity Y 打开 Activity B 时出现问题。我不能只返回 Activity A,因为 Activity A 依赖于 Activity X 的信息。如果我从Activity Y打开Activity B,那么我往上走,我应该去Activity B的parent,那里可以是A,也可以是另一个B

上面没有 canGoUpToActivityA() 部分的代码将解决我的问题。使用该代码,当我从 Activity Y 打开 Activity B 时,向上应该总是转到 B 的父级。这已经是正确的(B 只知道它的父级,不能是 A)。

但是,当我从 Activity A 打开 Activity B 时,然后我再往上,它会启动 Activity B 的父级。如果我直接从 Activity A 打开 Activity B (A -> B),这确实是我想要的。但是,当我从另一个 Activity B (A-> B -> ... -> B) 打开 Activity B 时,这就是问题所在。因为我应该去 Activity A,而不是 Activity B 的父级,它可以是另一个 Activity B.

我仍然不清楚你到底想要什么,所以我将把它分成几个片段:

如果你想启动 Activity B 的父级并确保它不是 "launching itself",你可以使用其他人提到的 singleTop 标志来确保只有一个B 的实例永远在顶部。你提到你对此没有问题,但你已经将其列为示例,所以请记住这一点。

您还提到在启动 Activity A 之前检查父项是否 A。如果您只想启动堆栈中的前一个 activity,则不需要 Intent。只要完成你的 activity 它就会退出堆栈,显示之前的 activity.

如果您有一组 activity 应该在返回时启动,您可以简单地启动它。此时,前面的 activity 是什么并不重要,因为您明确地为给定的 class 启动了 activity。同样,您可以查看 FLAG_ACTIVITY_REORDER_TO_FRONT 标志以确保不会重新创建现有的 activity。

最后,如果您有一些复杂的逻辑需要您了解完整的堆栈历史记录,您始终可以通过您的包传递数据。一个简单的例子是简单 class 名称的数组列表,因此您知道当前任务中的所有内容。


编辑:由于您还补充说您依赖于之前 classes 中的信息,我认为您需要的不仅仅是 class 名称。

请注意,您始终可以通过包传递数据,以便在所有后续活动中保留它们。您还可以通过调用 putExtras.

传递所有当前数据

而且,如果您的整个流程都面向子级,然后将数据传递回父级,请考虑使用 [startActivityForResult](https://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int))。这样,您可以设置结果代码和数据并完成您的 activity 以直接将信息传递给之前的 activity,而无需以正向流的方式启动新的 Intent。