I have a progress bar (swirly waiting style) defined in xml as:
Using android:configChanges
is bad practice, because it might get you in much worse trouble.
Also saving a variable at onSaveInstanceState
didn't work for me, since you won't get updates while the Activity is destroyed.
I ended up using a ResultReceiver inside a Fragment that doesn't get destroyed by using setRetainInstance(true)
.
A good article concerning this problem can be found here: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
Also see my answer here: https://stackoverflow.com/a/54334864/6747171
So am I right in thinking that the default Bundle saved by android does not include any changes made to to a ProgressBar View object?
You are right. Android will not save the state of progressBar
, or any other widget for that matter.
[Is] it correct to say that the only way to reinstate the correct visibility of the ProgressBar after an orientation change is to save a flag (e.g. boolean pbState = false/true) by overriding the method onSaveInstanceState and inspecting this flag in onRestoreInstanceState and setting the visibility accordingly?
Absolutely. About onRestoreInstanceState(Bundle)
: You can do without overriding this method. To confirm orientation change, check for savedInstanceState ==> Bundle passed to onCreate(Bundle)
against null
. If an orientation change has occurred, savedInstanceState
will not be null. On start of an activity, savedInstanceState
will be null
. Following code (which is basically what you proposed) should do the job:
Declare a global boolean variable:
boolean progressBarIsShowing;
In your onCreate(Bundle)
:
// savedInstanceState != null ===>>> possible orientation change
if (savedInstanceState != null && savedInstanceState.contains("progressbarIsShowing")) {
// If `progressBarIsShowing` was stored in bundle, `progressBar` was showing
progressBar.setVisibility(View.VISIBLE);
} else {
// Either the activity was just created (not recreated), or `progressBar` wasn't showing
progressBar.setVisibility(View.GONE);
}
Whenever you show progressBar
, set progressBarIsShowing
to true
. And toggle it when you dismiss progressBar
.
Override onSaveInstanceState(Bundle)
:
if (progressBarIsShowing) {
outState.putBoolean("progressBarIsShowing", progressBarIsShowing);
}
Caution: Check for when user browses away from your activity(via home button press etc). You might get a BadTokenException
if progressBar
is showing when the user does so.
You use the following line inside your activity tag in manifest.
<activity android:name="your activity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
In the above android:configChanges="orientation"
will maintain the state of your application while configuration change.