【问题标题】:Confused about singleTop mode对 singleTop 模式感到困惑
【发布时间】:2014-11-27 00:21:31
【问题描述】:

我在 android 文档中读到 singleTop 模式是这样的:

如果活动的一个实例已经存在于顶部 当前任务,系统通过 调用它的 onNewIntent() 方法,而不是创建一个新实例 的活动。活动可以被实例化多次,每次 实例可以属于不同的任务,一个任务可以有多个 实例(但仅当返回堆栈顶部的活动是 不是活动的现有实例)。

但是,我的应用程序的行为有所不同。我的主要活动在清单文件中定义了 singleTop 启动模式。这就是它表现异常的地方。

  1. 从启动器启动主要活动。
  2. 从主活动,开始子活动。
  3. 当用户按下后退按钮(或操作栏主页按钮)时,它会向主 Activity 发送一些额外的意图。这意味着需要更新主活动(取决于子活动中的用户操作。)
  4. 主要活动显示更新后的显示。

-- 奇怪的是这个--

  1. 在主活动中,按下返回按钮会再次返回到主活动。
  2. 第二次按后退按钮会调出启动器屏幕,然后我的应用程序会进入后台。

在第 5 步,为什么它再次调出主要活动?我认为 singleTop 将把主要活动放在前面,这是任务中当前堆栈的顶部。但从 #5 和 #6 中的行为来看,它似乎是在创建两个 main Activity 实例。

是我的理解不正确还是发生了其他我不清楚的事情。请帮助解释/澄清。谢谢。

我的子活动覆盖了它的 onBackPressed 方法。同样,主要活动 onNewIntent() 处理额外内容。

@Override
public void onBackPressed() {
    Intent intent = new Intent(this, MainActivity.class);
    intent.putExtra(MainActivity.UPDATE_ARG, true);
    startActivity(intent);
    super.onBackPressed();
}

注意:如果我使用 singleTask 模式,它的行为与我对 singleTop 的预期相同。但我在某处读到过要谨慎使用 singleTask 和 singleInstance。

【问题讨论】:

  • 回压不会发送意图,它会完成顶部活动。这些不是一回事。
  • @Karakuri 我忘了提,我已经覆盖了子活动的 onBackpressed() 方法,并在那里为主要活动传递额外内容(如果需要)创建了一个新意图。

标签: android android-activity


【解决方案1】:

来自发布的文档:

一个任务可以有多个实例(但前提是 后栈的顶部不是 Activity 的现有实例)。

来自您的代码:

当用户按下返回按钮(或操作栏主页按钮)时,它会发送 打算以一些额外的活动为主。这意味着主要 活动需要更新(取决于 sub 中的用户操作 活动。)

当用户按下返回按钮时,您的主要活动不存在于当前任务的顶部,而您的子活动位于顶部,因为它尚未销毁,因此它会创建另一个主要活动并且不要使用现有的活动,因为主要活动不是顶级的。 从文档中查看,注意backstack 包含当前前台活动

【讨论】:

  • 那么如何正确实现 singleTop 模式呢?我真的很困惑。
  • 你可以使用android:launchMode="singleInstance" 或者我认为你应该使用startActivityForResualt
  • 它违背了使用 singleInstance 只是为了具有 singleTop 模式行为的目的。如果我的子活动没有立即返回,那么使用 startActivityForResult 对我来说没有意义。当用户在子活动中停留的时间过长时,我遇到了我的应用程序因内存不足而被终止的情况。当它返回到 main 时,它挂了,因为 main 已经被系统清理了。
  • 谢谢顺便说一句,粗体字 backstack 包含当前前台活动帮助我理解并弄清楚了一些事情。
【解决方案2】:

为什么它再次调出主要活动?

好吧,因为当你这样做时你又开始了你的活动:

startActivity(intent);

您的 Activity 中的任何更新都应在 onStart 方法(或 onResume 如果适用)中执行。

【讨论】:

  • 我在 onResume 中有我的更新。我只抓住 onNewIntent 方法的意图。
  • 我不确定我是否完全理解您要完成的工作。当大多数用户/应用程序真的不必担心它时,我觉得你正在与 TaskStack 作斗争。我会尝试从不同的角度解决这个问题(比如启动活动以获得结果,或者有一个公共存储,活动 A 可以从中加载数据,活动 B 可以保存数据)。如果您尝试做的事情感觉很糟糕,那么它可能是。 :)
  • 我只想实现 singleTop 模式,在这种模式下我不需要重新定义主要活动,而是重用后台堆栈中现有的主要活动并将其置于顶部。我的主要活动显示了从 sqlite 数据库中获取的大量数据,并且重新实例化它将再次经历这一切,而重用和更新现有的数据几乎没有开销。
【解决方案3】:

我终于明白了这一切(我想!)。我会解释的。

android:launchMode 属性适用于 Activity,无论它是从主页启动器、从您的应用程序内部(或从另一个应用程序)启动的。

需要意图标志Intent.FLAG_ACTIVITY_CLEAR_TOP 来实现singleTop 行为。因此,我在开始活动之前创建意图时传递了该标志。

对于主要活动,这是我所做的:

@Override
public void onBackPressed() {
    Intent intent = new Intent(this, MainActivity.class);
    // these flags are important!!
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.putExtra(MainActivity.UPDATE_ARG, true);
    startActivity(intent);
    super.onBackPressed();
}

相应地,我在清单文件中声明了android:launchMode="singleTop"

【讨论】:

  • "android:launchMode 属性仅适用于您的应用的主要活动是从主页启动器(或其他应用)启动的情况。" 抱歉,您的结论根本不正确!我必须说的另一件事是当您使用launchModeIntent flag 时,Intent flag 会胜出并覆盖launchMode,但如果您不指定意图标志系统,请查看launchMod
  • 当我的结论错误时,你能告诉我吗?这是我到目前为止所理解的,我不知道其他与我的结论相矛盾的用例。
  • @mmlooloo 好的,我很好奇并试图测试其他东西,你是对的。 launchMode 确实会影响活动的启动方式,即使是在您自己的应用程序中也是如此。我将编辑我的帖子以反映更正。
猜你喜欢
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-24
  • 2022-01-04
  • 2011-06-10
  • 2016-08-14
相关资源
最近更新 更多