我有活动,可以启动 AsyncTask 。允许活动以纵向或横向显示。更改方向时,将销毁并重新创建活动。无论方向改变多少次,任务都会继续工作。它还会将结果成功返回给活动(根据CommonsWare的回答http://goo.gl/WF1yW)。
我想要实现的是:当活动因应用程序正在关闭而被销毁时 - 应该取消该任务。但是,当活动因方向更改而被销毁时 - 不应取消任务。
基本上问题是如何区分这两种情况:应用是关闭/方向改变。 在这两种情况下都会调用onDestroy()方法,并且没有简单的方法可以检查像isChangingOrientation()......
P.S。如有必要,我还可以考虑采用完全不同的方法。
答案 0 :(得分:9)
你可以使用isFinishing()
方法检查活动是否会被杀死,或者由于方向改变而调用onDestroy()
方法
@Override
protected void onDestroy() {
super.onDestroy();
if(isFinishing()){
Log.i("DEBUG", "App will Terminate ");
}else{
Log.i("DEBUG", "Orientation changed");
}
}
答案 1 :(得分:7)
我找到了一个令人满意的解决方案,我想分享。
仅在重新创建活动时才调用 onRetainNonConfigurationInstance()方法。更具体地说:Called by the system, as part of destroying an activity due to a configuration change, when it is known that a new instance will immediately be created for the new configuration.
我重写此方法并存储标志(说明是否已被调用)。然后在onDestroy(稍后调用)中,我检查这个标志,如果它是 false ,我取消了后台任务,因为Activity正在被销毁。如果它是 true ,这意味着已经调用了onRetainNonConfigurationInstance(),这意味着正在重新创建Activity,所以我让任务继续运行。
我本来希望有更好的解决方案,但却找不到。此解决方案的问题有两个:方法已弃用; 无保证该方法将被调用(根据文档)。在实践中,该解决方案适用于我,所以我将使用它...
答案 2 :(得分:3)
一般来说,你不想定义onConfigurationChanged(),因为要把一切都弄好是很难的。最好的方法是在方向改变时让应用程序被杀死并重新创建。
为了简化转换,您可以实施onRetainNonConfigurationInstance()。当系统知道您的应用程序几乎立即重新启动时,系统将调用此方法。在onRetainNonConfigurationInstance()中,您将任意对象传递回系统('this'是一个合理的选择)。然后,在onCreate()
方法中,调用getLastNonConfigurationInstance()以获取以前保存的对象。这使您可以非常快速,轻松地从上一次调用中恢复您的状态。我相信即使运行线程和打开套接字也可以通过这种方式传递。
有关详细信息,请参阅Save cache when rotate device。
答案 3 :(得分:2)
在此处查看以便更好地了解Android生命周期: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
您可以使用onConfigurationChanged()检测活动中的方向更改。您可以使用onDestroy()方法确定您的活动即将被杀死的时间。
答案 4 :(得分:0)
我在一些研究后发现的最好的方法是创建一个应用程序类并依赖onTrimMemory()方法。这种方法的问题 - 如果屏幕超时或屏幕被按下电源按钮锁定,onTrimMemory()不会被调用,所以我必须单独实现该逻辑。
/**
* When your app's process resides in the background LRU list:
* TRIM_MEMORY_BACKGROUND
* TRIM_MEMORY_MODERATE
* TRIM_MEMORY_COMPLETE
*
* When your app's visibility changes:
* TRIM_MEMORY_UI_HIDDEN
*/
@Override
public void onTrimMemory(final int level) {
super.onTrimMemory(level);
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
|| level == ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
|| level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE
|| level == ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
// App went in background
}
}
以下代码是检测屏幕锁定。我在ActivityLifecycleCallbacks方法之一中实现了这段代码 - onActivityStopped()
final PowerManager powerManager = (PowerManager) getAppContext().getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
if (!powerManager.isScreenOn()) {
// Screen locked
}
} else {
if (!powerManager.isInteractive()) {
// Screen locked
}
}
答案 5 :(得分:-1)
如果您的应用面向API级别13或更高级别,则应在manifest.xml中设置此配置
<activity
android:configChanges="orientation|screenSize"
...
/>