如何区分是否将onDestroy()作为配置更改序列的一部分进行调用?

时间:2011-07-16 10:58:21

标签: android android-activity ondestroy

在我的Activity中,需要在onDestroy()中销毁一些外部事物(服务)。但是当配置发生变化时(例如键盘翻转),我不希望这样,因为它会立即恢复。

所以问题是:如何区分onDestroy()是否是由Back-key press或部分配置更改过程引起的?

在@ CommonsWare的回答之后,它会非常简单,例如:

@Override 
onDestroy() { 
  if (mIsChangeConfig == true) { 
    mIsChangeConfig = false: 
  } else { 
    stopService(); 
  } 
} 

@Override 
onRetainNonConfigurationInstance() { 
  mIsChangeConfig = true; 
}

3 个答案:

答案 0 :(得分:24)

在Android 3.x(API级别11)中,您可以调用isChangingConfigurations()以查看活动是否因配置更改而被销毁。

在此之前,覆盖onRetainNonConfigurationInstance()并将布尔数据成员(例如isChangingConfigurations)设置为true,并在onDestroy()中检查该数据成员。

答案 1 :(得分:6)

这可能适合你(来自How to distinguish between orientation change and leaving application android):

  

使用Activity的isFinishing()方法。

示例代码:

@Override
protected void onDestroy() {
  super.onDestroy();

  if (isFinishing()) {
    // Do stuff
  } else { 
    // It's an orientation change.
  }
}

答案 2 :(得分:0)

对于必须在onStop()上执行X操作的情况,我有一个解决方法,但如果配置发生更改,您不希望它完成(显然您没有isChangingConfigurations()可用)。

该技术包括在AsyncTask上执行此X操作并延迟。您可以在onStop()/ onPause()和onRetainCustomNonConfigurationInstance()中调用AsyncTask来取消该任务。这样,例如,如果用户按下主页键,则X代码将在后台执行。但是,如果屏幕旋转,则不会执行X代码,因为任务在执行之前将被取消(这就是延迟的含义)。

我正在使用它来解决唤醒锁的问题:在onPause()上释放它们,但是如果用户改变了屏幕方向则不能。

这是我的代码:

private class ReleaseWakeLockDelayedTask extends AsyncTask<WakeLock, Integer, Integer>{

    @Override
    protected Integer doInBackground(WakeLock... params) {

        try {
            // Delay so that onRetainCustomNonConfigurationInstance is in
            //  time of cancelling the task
            Thread.sleep(5000);  
        } catch (InterruptedException e) {}

        if(isCancelled()) return null;
        releaseWakeLock(params[0]); // own method that calls the actual release
        return null;
    }
}


@Override
public Object onRetainCustomNonConfigurationInstance() {
    ...
    if(mReleaseWakeLockTask != null && mReleaseWakeLockTask .getStatus() != AsyncTask.Status.FINISHED){
        mReleaseWakeLockTask.cancel(true));
    }
    ...
}

@Override
protected void onPause() {
    // create and call the task
    boolean wRun;

    if(mReleaseWakeLockTask != null){
        if(mReleaseWakeLockTask .getStatus() != AsyncTask.Status.FINISHED) wRun= false;
        else wRun= true;
    }else wRun = true;

    if(wRun){
        mReleaseWakeLockTask = new mReleaseWakeLockTask ();
        mReleaseWakeLockTask .execute(wakeLock);
    }
}

希望它有所帮助!