How to distinguish whether onDestroy() is called as part of configuration change sequence?
Asked Answered
K

3

19

In my Activity some external thing (service) need to be destroyed in onDestroy(). But I do not want this when configuration change happens (e.g. keyboard flips out) because it will be restored right away.

So the question is: how to distinguish whether onDestroy() is caused by say Back-key press or part of config change process?

after @CommonsWare's answer it would be pretty simple) something like:

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

@Override 
onRetainNonConfigurationInstance() { 
  mIsChangeConfig = true; 
}
Keel answered 16/7, 2011 at 10:58 Comment(2)
show some code. At least pseudo code.. This isn't giving enough info.Lewls
added pseudo-code to question...Keel
S
25

In Android 3.x (API Level 11), you can call isChangingConfigurations() to see if the activity is being destroyed due to a configuration change.

Prior to that, override onRetainNonConfigurationInstance() and set a boolean data member (e.g., isChangingConfigurations) to true, and check that data member in onDestroy().

Scoles answered 16/7, 2011 at 12:4 Comment(8)
Thanks, I got an idea... the only trick left is how to clear this flag off, but hope I'll figure it out)Keel
Also, if using the support library FragmentActivity (android.support.v4.app.FragmentActivity) on pre-Honeycomb, onRetainNonConfigurationInstance() is declared final, but you can override onRetainCustomNonConfigurationInstance() instead for the same effect. (This is slightly non-obvious because the deprecated tag takes you to a completely different API that cannot be used in this way.)Atombomb
If I understand the documentation correctly then isChangingConfigurations() is available already in onStop() but onRetainNonConfigurationInstance() is called between onStop() and onDestroy(), if at all. So these options are unfortunately not entirely equivalent.Zakaria
how would you check it in the onCreate method?Vaunting
@Scoles what's the difference between using isChangingConfigurations() and isFinishing()?Vaunting
@Scoles I mean the logic. instead of using isChangingConfigurations, I could use !isFinishing , which is supported from before API11 ? are the equivalent in case I use them in the onDestroy method (except for returning the opposite) ?Vaunting
@androiddeveloper: Well, in the source code, they are independent -- it's not like isChangingConfigurations() is implemented as !isFinishing(). Probably most of the time your assumption will hold, but I would not be surprised if there are edge cases in which it does not.Scoles
@Scoles Yes I thought so, but I can't think of any kind of end case.Vaunting
P
6

This may do the trick for you (from How to distinguish between orientation change and leaving application android):

Use the Activity's isFinishing() method.

Sample code:

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

  if (isFinishing()) {
    // Do stuff
  } else { 
    // It's an orientation change.
  }
}
Pamela answered 27/3, 2014 at 16:16 Comment(3)
This is also possible. I wonder though what's the difference between using it and "isChangingConfigurations" (aside from them being the opposite of each other).Vaunting
!isFinishing() implies either an orientation change or going into the backstack.Postulate
it's better to call isFinishing in onPause as onDestroy may not always be called according to the docs at developer.android.com/reference/android/app/… : Note: do not count on this method being called as a place for saving data!Chiffon
P
0

I have a workaround for the cases when something X has to be done on onStop(), but you don't want it to be done if there is a configuration change (and obviously you don't have isChangingConfigurations() available).

The technique consists on doing this X action on an AsyncTask and delayed. You call the AsyncTask in onStop()/onPause() and in onRetainCustomNonConfigurationInstance() you cancel the task. This way, if the user presses the home key, for example, the X code will be executed on background . However, if there is a screen rotation, the X code will not be executed because the task will be cancelled before it's executed (that's the meaning of the delay).

I'm using it for example to solve problems with wakelocks: releasing them on onPause() but not if the user changes the screen orientation.

Here is my code:

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);
    }
}

Hope it helps!

Polyandry answered 11/4, 2013 at 0:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.