3

活动生命周期让我头疼。http://developer.android.com/reference/android/app/Activity.html上的文档在描述可见性概念时是如此模棱两可,以至于我无法弄清楚何时onStop()调用 vs onPause()

比较文档中的以下两个语句:

(取自生命周期图的正下方)

和方法可以被多次调用,因为活动对用户可见和隐藏onStart()onStop()

对比

(在带有“可杀死”列的蓝色表中进一步向下)

onPause()当系统即将开始恢复以前的活动时调用。

我从第一句话中了解到的是,在“隐藏”时onStop()调用活动。我猜“隐藏”是指另一项活动已恢复并完全覆盖活动的时间。但是第二个引用然后指出当另一个活动即将开始恢复时调用。那不是也完全隐藏了活动A吗?这两种情况似乎都意味着该活动变得“隐藏”,不是吗?根据我可能的错误解释,并且在相同的情况下被调用。AABAonPause()AonPause()onStop()

该文档似乎在隐藏(onStop()被调用)和部分可见性(onPause()被调用)之间也有所不同。但是什么时候活动仍然是部分可见的?他们是字面意思吗?或者,当一个活动启动一个覆盖整个屏幕的新活动(活动调用 startActivityForResult 并启动一个日期选择器活动)时,它仍然可以被视为“部分可见”吗?活动肯定不会被调用 onStop 吗?它应该随时收到结果!

所以我试图弄清楚我没有得到什么。我知道对 onPause 的调用是有保证的。那将是当活动A失去焦点(设备进入睡眠模式、屏幕锁定等)时,另一个活动B占据前台(活动B可能或可能不是由活动发起A)。但是在什么时候onStop()调用活动A

有多少活动堆积在活动堆栈上的活动 A 上是否重要?是否存在两种不同的“可见性”定义?

对文字墙感到抱歉,但我真的很沮丧:S

所以问题是:究竟在哪些情况下被认为是“隐藏”的活动onStop()才会被调用?

编辑:

我在每个 onX 方法中插入了 Toast 通知,并发现了一些额外的奇怪之处:

  1. 按下 Home 按钮将始终调用 onStop()。但启动应用程序不会调用onRestart(). 相反,它调用onCreate(). 这对我来说似乎很奇怪,但好吧......
  2. 当“USB Mass Storage”活动在主活动之上启动时,onStop()被调用。并且在退出 USB 存储活动时,会调用返回主活动,onRestart()而不是onCreate().
  3. 当设备进入睡眠模式并被唤醒时,活动只经过onPause()andonResume()循环。

最后一点是预料之中的(尽管我无法让它适合生命周期图)。但是 1. 和 2. 怎么了?

在第一点,我期待onRestart()在再次开始活动时接到电话。为什么它取消分配活动并onCreate()改为调用?

并看看第 2 点:根据文档:当“另一个活动出现在活动前面”时,onPaused()应该调用。当 USB 存储活动出现时,不就是这样吗?它没有调用onPause(),它经历了onStop()-OnRestart()循环!显然,文档没有考虑“另一个活动出现在活动之前”的情况。那么究竟发生了什么?

4

2 回答 2

2

好的,我想我现在明白了。

1.

第一点的关键是这个链接:

http://code.google.com/p/android/issues/detail?id=2373

它是一个错误。链接中有一些代码完全解决了创建新根活动实例的问题,而不是仅仅重新启动最后一个活动活动(在按下主页按钮之前)。

我将代码放在 onCreate 方法的顶部,就在 super.onCreate 调用的下方:

if (!isTaskRoot()) {
    final Intent intent = getIntent();
    final String intentAction = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) &&
            intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
        finish(); return;
    }
}

请注意,我在完成后添加了 return 语句,因此在检测到错误的情况下,onCreate 方法的其余部分不会运行。

2.& 3.

第二点和第三点的关键是这两个环节:

http://answers.oreilly.com/topic/2692-android-programming-understanding-the-activity-life-cycle/

如何制作Activity,不覆盖全屏

原来,“能见度”真的是字面意思!因此,当文档说“另一个活动出现在活动前面”时,碰撞活动后面的活动仍然部分可见。这意味着 Android Activity 管理器必须检查碰撞的 Activity 是否是全屏 Activity:如果是,onStop()则在前一个 Activity 上调用。如果不是,则onPaused()改为在前一个活动上调用 then。

这简单地解释了为什么 USB 存储管理器导致onStop()被调用。

这也意味着当设备进入睡眠模式时,活动管理器将其视为非全屏活动,即使技术上主要活动完全隐藏在其后面。

(有关如何制作非全屏活动,请参阅第二个链接)

有趣的是,下拉窗口(带有通知)不会调用onPause()(也不会调用onStop()),即使它作为非全屏活动是有意义的。这一定是某种例外,我将自己调查。

这也意味着onStop()-onRestart()循环可能比onPause()-onResume()循环更常见(尽管两者都必须考虑在内),因为活动可能更多时候是全屏活动(我个人认为文档表明相反:onPause-onResume更常见,但也许这只是我)。

此外,这必须意味着当主 Activity 为结果启动新的全屏 Activity 时,主 Activity 将首先停止,然后在完成检索结果的 Activity 时重新启动。

所以现在唯一的问题是如何最好地处理被释放的暂停活动(意味着它被非全屏活动覆盖)(尽管这种情况很少见)。可能会有哪些挑战?

但这超出了这个问题的范围。

于 2011-12-29T14:36:27.367 回答
0

终于找到了这个:您可以使用 onWindowFocusChanged() 检测状态栏下拉

如何使用 OnWindowFocusChanged 方法

于 2016-12-02T20:54:20.933 回答