Reputation: 1589
I have a weird issue that happens on Android 10, when I start new landscape activity, the activity below will recreate.
Assume there're two Activity
classes:
ActivityA: orientation = unspecified
ActivityB: orientation = force landscape, full screen, opaque
If I start ActivityB
from ActivityA
, the logs of lifecycle event:
D/ActivityA: onPause() called
D/ActivityB: onCreate() called
D/ActivityB: onStart() called
D/ActivityB: onResume() called
D/ActivityA: onStop() called
D/ActivityA: onDestroy() called
D/ActivityA: onCreate() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityA: onPause() called
D/ActivityA: onStop() called
Can clearly see that ActivityA
is recreated, moreover somehow ActivityA#onResume
is called after ActiviyB#onResume
??
Okay, so now we have ActivityB
on top of the stack, then I press back button:
D/ActivityB: onPause() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityA: onPause() called
D/ActivityA: onStop() called
D/ActivityA: onDestroy() called
D/ActivityA: onCreate() called
D/ActivityA: onStart() called
D/ActivityA: onResume() called
D/ActivityB: onStop() called
D/ActivityB: onDestroy() called
ActivityA
is recreated again?
As I see in my device, there's an animation that ActivityA
rotates into landscape mode before ActivityB
becomes visible, and when ActivityB
exits, ActivityA
again rotates back to portrait mode. This behavior may cause ActivityA
recreate again and again.
It messes up a lot, do you know how to prevent ActivityA
recreate on this case, or this is a bug of Android itself?
I can handle configuration change on ActivityA
easily, the problem is ActivityA
has a very complex view structure, recreate it unnecessary causes UI lagging, moreover activity's lifecycle callback messy also cause broken logic.
I just figured out that recreate()
method is invoked twice by AppCompatDelegateImpl
class, that's why I get weird lifecycle behavior:
Upvotes: 2
Views: 1297
Reputation: 4951
This looks like a device-specific bug.
I tried your code as it is on Pixel 3a (API 29 & 30) emulator. This is what I get:
On starting ActivityB
from ActivityA
:
D/MainActivityA: onPause() called
D/MainActivityB: onCreate() called
D/MainActivityB: onStart() called
D/MainActivityB: onResume() called
D/MainActivityA: onStop() called
On back button press:
D/MainActivityB: onPause() called
D/MainActivityA: onStart() called
D/MainActivityA: onResume() called
D/MainActivityB: onStop() called
D/MainActivityB: onDestroy() called
You should file an issue with the appropriate Android build and Device used
Thoughts on Update 2 in the question:
The logs show that onConfigurationChanged(Configuration)
is being called. Documentation points out that Activity will be recreated on runtime configuration changes.
What you can do is override onConfigurationChanged(Configuration)
in your Activity and log the Configuration object to see what device configuration was changed. It may be Orientation
, Screen size
, ScreenLayout
or Keyboard availability
Upvotes: 1
Reputation: 992
Activity is recreated after each rotation by default as it's told on official Activity Lifecycle onDestroy() documents.
If you expect the activity’s UI state to remain the same throughout a configuration change, such as rotation, you should preserve the user’s transient UI state using a combination of ViewModel, onSaveInstanceState(), and/or local storage as it's explained in the Saving and restoring transient UI state
You can override this behavior with config changes attribute of the activity tag in AndroidManifest. For further details and different options, see Handle configuration changes
Finally, you can learn more about Activity Lifecycle in Context of Screen Rotation here.
Upvotes: 0
Reputation: 7897
Recreating activities on landscape/portrait is a feature of Android (not a bug) made by design because it's easier programmatically to just redraw the UI rather than figure out repositioning/resizing of elements. You should get the same effect when just flipping orientation on A even without B. This is also well described in the Android documentation (https://developer.android.com/guide/components/activities/state-changes#cco)
This shouldn't be too much of a problem, so long as you don't keep any references to the activity itself; The resources at this point are already cached, so there is little to no flash I/O, and most of the work will be recreating the views.
Upvotes: 1
Reputation: 95578
Probably isn't much you can do about this behaviour. I would suggest the following, if it doesn't cause you too many problems:
android:configChanges="orientation"
to the manifest entry for ActivityA
onConfigurationChanged()
in ActivityA
and handle the orientation change yourselfThis will prevent Android from killing and recreating ActivityA
during an orientation change.
Upvotes: 3
Reputation: 13
it's not only you facing this problem (many people are) this is a bug which is to be fixed and it shouldn't be messed actually can I know which device you are using? In comment you may tell.
Upvotes: 1