由于方向已更改或应用正在关闭,活动是否被销毁?

时间:2012-03-05 22:41:00

标签: android android-asynctask android-activity

我有活动,可以启动 AsyncTask 。允许活动以纵向或横向显示。更改方向时,将销毁并重新创建活动。无论方向改变多少次,任务都会继续工作。它还会将结果成功返回给活动(根据CommonsWare的回答http://goo.gl/WF1yW)。

我想要实现的是:当活动因应用程序正在关闭而被销毁时 - 应该取消该任务。但是,当活动因方向更改而被销毁时 - 不应取消任务。

基本上问题是如何区分这两种情况:应用是关闭/方向改变。 在这两种情况下都会调用onDestroy()方法,并且没有简单的方法可以检查像isChangingOrientation()......

P.S。如有必要,我还可以考虑采用完全不同的方法。

6 个答案:

答案 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"
...
/>