【问题标题】:Activity onStart() not called when resuming an recreated activity from a stack从堆栈恢复重新创建的活动时未调用活动 onStart()
【发布时间】:2016-05-11 19:16:26
【问题描述】:

长话短说:我目前正在开发一款小型安卓游戏。一项功能是能够更改应用程序主题。当用户更改主题时,会在整个应用程序中广播一个事件,并且所有活动的活动都会调用 recreate() 来应用新主题。

问题: 假设有一堆活动:A、B、C。所有活动都将按照它们打开的顺序接收事件并调用 recreate()。这些是将被调用的生命周期事件(按顺序):

  • Activity A 将调用 onDestroy()、onCreate()、onStart()、onResume() 和 onPause()
  • Activity B 将调用 onDestroy()、onCreate()、onStart()、onResume() 和 onPause()
  • Activity C 将调用 onPause()、onStop()、onDestroy()、onCreate()、onStart()、onResume()。

请注意,活动 A 或 B 均未调用 onStop()。 当这些活动被返回时(例如按下后退按钮),它们变得可见时不会调用 onStart(),而是会调用 onResume()。这与活动生命周期文档中的规定相反。

问题:我在这里做错了吗?是否有另一种方法可以在不破坏 Activity 生命周期的情况下重新启动应用程序中的所有 Activity?

【问题讨论】:

    标签: android android-activity android-lifecycle


    【解决方案1】:

    我认为您在这里采取了错误的方法。您不应使用框架调用来更改主题。您遇到的问题是您没有像框架那样调用onStop,但即便如此......

    您的方法不正确的主要原因是,如果 Activity 不可见,Android 可能已经销毁它。因此,向它发送调用框架方法的事件不仅在这一点上是不必要的,而且可能导致不可预测的状态和行为。甚至可能导致崩溃。

    对于主题或任何 UI 组件的更改,您应该在 onResume 中处理 - 换句话说,当用户返回到 Activity 时处理 UI 元素的更改。这样做的一种选择是通过startActivityForResult 传递标志。

    更好的是,使用sharedPreferences(或使用其他方法)使您的主题选择保持不变,然后在恢复Activity 时从中读取。无论用户如何访问Activity,这将确保选择正确的主题。

    编辑:

    请注意,Activity 框架方法是 public 并不是因为它们应该随时或由其他类访问,而是因为它们需要在您的应用程序中实现。它们不打算在框架外调用。

    您应该注意,在Activity 的官方文档中,您调用的所有方法都没有列为“公共方法”(http://developer.android.com/reference/android/app/Activity.html#Activity())。您正在以不受支持的方式使用它们。但是,我指出这一点只是为了让您意识到这一点,并且它不是解决此问题的普遍接受的方法。

    【讨论】:

    • 重新创建事件(我在这里使用 EventBus)仅在每个活动的 onCreate() 和 onDestroy() 之间注册,因此没有问题。如果主题发生变化,采用 startActivityForResult() / onResume() 方式将导致每个恢复的活动出现难看的闪烁,我正试图避免这种情况。此外,我正在使用的活动的 recreate() 方法是 API 11 中添加的公共调用。
    • 我编辑了我的回复——即使在这种方法中使用 EventBus 也是我会避免的。你测试过“丑陋的闪烁”吗?我假设“是” - 如果是这样,您应该考虑动画或其他处理此问题的方法。也许在这里发布这个问题?因为您不应该在 Activity 不可见时调用“onStart”或“onResume”——这可能是问题的一部分,但这只是一种猜测。
    • 我认为你的问题有点错误。我从来没有说过我在调用这些生命周期方法。我说这些方法是由操作系统调用的,我列举了顺序,指出即使活动不可见,onStop() 也不会被调用。我只使用公共方法 recreate() 来触发活动重新创建。此方法记录在这里:developer.android.com/reference/android/app/…
    • 你是对的,我不明白你在做什么。但是,我试图解决的问题仍然有效。调用reCreate 不是合适的方法。当Activity 不可见时,您正在强制不适合调用的生命周期调用。尽管您有一个非常有创意的方法,但我认为这不是该方法的预期用途。我试图回答你的问题,“我在这里做错了什么吗?” - 是的。例如,您正在为后台的 Activity 强制调用“onCreate”。你不应该那样做。
    • 是的,在暂停、停止的活动上调用 recreate() 会导致意外行为。感谢您指出!
    【解决方案2】:

    这完全符合文档。

    http://developer.android.com/training/basics/activity-lifecycle/starting.html

    如果您查看图表,则无论如何都会在返回活动时调用 onResume,但 onStart 不会。

    【讨论】:

    • 是的,但是相同的文档指出,如果一个活动被完全隐藏,那么 onStop() 将被调用 - 在这种情况下它不会。
    【解决方案3】:

    如果你想改变 UI 相关的组件,那么你必须使用 OnResume 方法而不是重新创建所有的活动。喜欢以下。

        @override
        onResume()
        {
        textview.setText("Change text When activity resumes");
        }
    

    【讨论】:

      【解决方案4】:

      上面的同事反应很好。 您报告的行为。 onstart 和 onResume 不会被调用。我已经看到它发生在热代码交换上。值得停止应用程序并调用重建。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多