Activity onStart() not called when resuming an recreated activity from a stack
长话短说:我目前正在开发一款小型Android游戏。其中一项功能是能够更改应用程序主题。当用户更改主题时,会在整个应用程序中广播一个事件,所有活动都调用recreate()来应用新主题。
问题:假设有一组活动:a、b、c。所有活动都将按其打开的顺序接收事件,并调用recreate()。这些是将被调用的生命周期事件(按顺序):
- 活动A将调用OnDestroy()、OnCreate()、OnStart()、OnResume()和OnPause()。
- 活动B将调用OnDestroy()、OnCreate()、OnStart()、OnResume()和OnPause()。
- 活动C将调用onPause()、onStop()、onDestroy()、onCreate()、onStart()、onResume()。
请注意,活动A或B都没有调用onstop()。当这些活动被返回(如按后退按钮)时,它们在可见时不会调用onStart(),而是调用onResume()。这与活动生命周期文档中所述的相反。
问题是:这里有什么我做错的地方吗?是否有其他方法可以在不影响活动生命周期的情况下重新启动应用程序中的所有活动?
我认为你在这里采取了错误的做法。您不应该使用框架调用来更改主题。你所面临的问题是,你并不像框架那样调用onStop,但即使如此……
您的方法不正确的主要原因是,如果不可见,Android可能已经销毁了一个Activity。因此,向它发送调用框架方法的事件不仅在当时是不必要的,而且可能导致不可预知的状态和行为。甚至可能导致撞车。
对于主题或任何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来实现这个方法也是我可以避免的。你测试过"难看的闪烁"吗?我假设"是"-如果是这样,您应该考虑动画或其他处理此问题的方法。也许把那个问题贴在这里?因为当活动不可见时,您不应该调用"onstart"或"onresume"——这可能是问题的一部分,但这只是一个猜测。
- 我觉得你的问题有点错。我从未说过我在调用这些生命周期方法。我说过这些方法是由操作系统调用的,我枚举了顺序,指出即使活动不可见,也不会调用onstop()。我只使用public方法recreate()来触发活动重新创建。此方法记录在这里:developer.android.com/reference/android/app/…
- 你说得对,我不明白你在做什么。但是,我试图解决的问题仍然有效。调用reCreate不是合适的方法。当Activity不可见时,您强制使用不适合调用的生命周期调用。虽然你有一个非常有创意的方法,但我不认为这是该方法的预期用途。我正试图回答你的问题,"我在这里做的事情有问题吗?"-是的。例如,您正强制调用后台活动的"onCreate"。你不应该那样做。
- 是的,对暂停的、停止的活动调用recreate()会导致意外的行为。谢谢你指出!
以上同事反应很好。你报告的行为。不调用OnStart和OnResume。我看到了它发生在热代码交换上。值得停止应用程序并调用重建。
如果要更改与UI相关的组件,则必须使用OnResume方法,而不是重新创建所有活动。喜欢跟随。
1 2 3 4 5
| @override
onResume()
{
textview.setText("Change text When activity resumes");
} |
这与文档完全一致。
http://developer.android.com/training/basics/activity-lifecycle/starting.html
如果你看图表,当你返回到一个活动时,onresume会被调用,而不管onstart是什么。
- 是的,但是相同的文档声明,如果一个活动完全隐藏,那么会调用onstop(),在本例中不会。