如何检测父 activity 是否在返回堆栈中并且可以在不创建新实例的情况下上升?
How to detect if a parent activity is in the back stack and can go up without creating a new instance?
我的系统有几个 Activity
、Activity X
、Activity A
、Activity B
和 Activity Y
。 Activity X
由 A
的列表组成。如果我们点击 A
,它将转到 Activity A
。 Activity A
由 B
的列表组成。如果我们点击 B
,它将转到 Activity B
。 Activity 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
的父级可以是另一个 B
或 A
。 B
只认识他爸妈。问题是如何在不从 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);
}
}
编辑
如果有人因为认为解决方案就像 singleTop
到 Activity 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。
我的系统有几个 Activity
、Activity X
、Activity A
、Activity B
和 Activity Y
。 Activity X
由 A
的列表组成。如果我们点击 A
,它将转到 Activity A
。 Activity A
由 B
的列表组成。如果我们点击 B
,它将转到 Activity B
。 Activity 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
的父级可以是另一个 B
或 A
。 B
只认识他爸妈。问题是如何在不从 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);
}
}
编辑
如果有人因为认为解决方案就像 singleTop
到 Activity 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。