I have gone through different posts and questions for handling rotation and AsyncTask. In each post it is mentioned that using android:configChanges
is a bad practice. But i didn't find the actual reason why it is discouraged and why it is a bad practice. What are the disadvantage if we use android:configChanges to handle orientation.
Note:
I know it is already answered how to handle orientation and AsyncTask. but I want to know reason behind not using android:configChanges.
Well, you need to remember that an Activity can be restarted for multiple reasons.
For example, one of these reasons is when your app is in the background and the OS decides to kill it (with your Activity, of course) to reclaim memory.
When you return to your app, the OS will try to recreate your Activity as you left it, but will fail to do so, because you decided not to bother with it, just used android:configChanges in your Manifest.
If you make sure your app can recover properly from a restart, android:configChanges might not be necessary at all. Because of this, the need to use android:configChanges might indicate some flaw in your app, that may worth to take a look at.
It's not bad practice to use android:configChanges, but it pretty easily can be, if you don't understand exactly what you're doing.
To sum up all what i got form #user13 answer and other stackoverflow questions and blog posts i would like to share my finding to clear some very important aspects.
(user13) It's not bad practice to use android:configChanges, but it pretty easily can be, if you don't understand exactly what you're doing
Using this technique prevents you from easily using configuration specific resources. For instance, if you want your layout or drawables or strings or whatever to be different in portrait and landscapes, you have to manage it yourself if you use android:configChanges.
You need to override and use onConfigurationChanged() method to perform specific action if you decide to use android:configChanges
As user13 mentioned Activity is recreated not just due to orientation change but there are multiple reasons due to which activity can be restarted. Therefor activity restart should be handled for all causes. using android:configChanges only handles one case and there will be unhandled cases of activity restart which will cause a potential bug.
There are multiple and better ways to handle activity restart and plenty of help is also available on stactoverflow so android:configChanges should be used as a last resort according to documentation.
Using android:configChanges is good practice if you know what you are doing.
Just always test how your application how it behaves when it is restarted by system to stay comfortable for user so some state has to be saved all the time but not all.
With config changes like this:
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Your application will restart rather rarely on new devices that have a lot of memory. If it restarts it's not so unexpected for user anyway, as user had attention elsewhere and came back to app. User don't have to be in exact same state after restart if it happens by manual killing of application or application restart because of some other heavy tasks (playing game) user is doing, the user experience is important here.
If you need to refresh List just for different layouts for orientations changes or you need to hide some view elements you can call:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
_list.reloadData();
_editorButton.visible(isPortrait());
}
(I use my custom classes but you get the point)
Related
After API 28 the order of execution of onSaveInstanceState() and onStop() is changed.
Referring to this paragraph from the documentation:
The reason for that change is the ability to firstly execute fragment transactions and then save state. Referring to this paragraph from the documentation:
What are the gains after this change?
Are there other reasons behind this change?
It's indeed a matter of consistency, because method onStop() can still modify the instance state.
When moving onSaveInstanceState() to the end of the timeline, those changes will not be lost.
While I am not a Google employee and have not contributed to this, the change also affected activities if I correctly recall, and I'd imagine the reasoning has to do with the fact that before this change, the call to save the state, was maybe going to happen if/when the Framework considered somewhat appropriate after onPause.
The behavior was quite unpredictable and made the lifecycle methods unreliable to trust.
With (Google Devs) refactoring of the entire FragmentManager and its behavior, this change was most likely driven by consistency. (and unknown to me, perhaps, other technical details we're not familiar with).
In short, the framework is now consistent in the calls, as they are guaranteed to occur after onStop (for API 28+), which ensures that when you re-create the activity/fragment, the state will be correct (and saved).
Like I mentioned at the beginning, I am not a Google developer, but the way it was before was a clusterf**k of uncertainty, and this change brought some hope to save the Fragment apis from their ultimate demise.
Sometime in the middle of this, using multiple activities was not cool anymore, and we all wanted a single activity with many fragments, and nav component to seamlessly move across the stack (not having to worry to much about "defects" in the original design), as this and many other details were polished across the journey that got us here, to a more stable Fragment platform if you so desire to use it.
Before all these "fixes", the Framework API was prone to many errors and inconsistencies sometimes leading to runtime crashes. I can imagine how this and many other fixes, were aimed at reducing this API to a perfectly functional feature, so that other tools like Navigation Component, Lifecycles, ViewModels, etc. could all work in harmony without having to worry about "oh, the Fragments are special and need further logic to handle its buggy behavior".
Despite all this, Fragments are slowly starting to become "an old thing" as more apps start to incorporate Jetpack Compose.
I apologize for my English but translated with google. I'd like to understand why Google with Android restarts the activity at each change and you lose all the data displayed. How do you solve this problem? Could not they make it optional this thing?
On every forum I read to use the methods onSaveInstanceState, onRestoreInstanceState, onConfigurationChanged, but how to use them is not explained well. If I have a complex application, with many objects, with EditText, with Markers, Polygons, I'm forced to save everything by hand with temporary variables? There is another way faster and easier to do it? Do you have any practical example to show me? I hope you know help me understand, thank you all.
It is an optional thing. In your manifest, add android:configChanges="orientation|screenSize" to your activity and it will turn off that behavior.
Really there's only 1 good circumstance to not override it- if you have no AsyncTasks, no Threads, no Loaders, no bound services, AND you have separate layout.xml files for landscape and portrait. That's about the only time it doesn't cause more pain to recreate than it saves. It's google's biggest screwup in the API.
In our application when a user switches between modes (different user/ different type of screen) the activity recreates itself (by an explicit call to recreate() ). This behavior was added by a external programmer we hired. He states this is completely normal to do.
The problem I have with this is that 99,9% of all activity state is the same. But when the activity is recreated all data is queried again, consuming quite a bit of time.
Is this a normal pattern? Or is it just as good to only change the data to suit the new situation?
To me it seems kind of strange to manually recreate the whole Activity just to reload some data. In any case just updating the data which has actually changed seems like a much better approach. Especially if you say that it takes quite a bit of time to reload all the data.
The only thing I can think of right now which requires to recreate the Activity is changing the locale or something like, but even that I would not recommend unless it is really necessary. If you are not dealing with configuration changes, e.g. locale, there is no reason to recreate the whole Activity just to reload some data.
I would say it's "normal" in the sense that Activities are recreated all the time by the system, so this just adds another event in which that would happen. Though this is, on it's own, really weird way of going about it. A better, more efficient, cleaner way would be to swap out Fragments on "mode change". You can have a UI fragment for each "mode" and the data stored in a retained Fragment that each one pulls from. This would also help in the sense that the UI doesn't have to be recreated completely with each Fragment swap.
However, if you must, it is an absolute requirement that you follow the same data storage/retrieval methods that you would if the system was killing and recreating the Activity. See How to save state during orientation change in Android if the state is made of my classes?
Basically, you shouldn't be recreating data you already have.
I have an android app that has to load very large files on start up. any time it switches orientations, it has to destroy and recreate the activity, causing the large files to reload. this takes about 30 seconds, this is pretty inconvenient if I were to actually publish this. I am sure that I am doing something wrong here. I have heard of onSaveInstanceState() and onRestoreInstanceState(), but I have no idea how to use them. does any body know how I could use this to speed up the Orientation change?
Use onRetainNonConfigurationInstance() to pass your data from the old activity to the new activity.
Or, store the data in a static data member (but be careful about garbage collection).
Or, store the data in a custom Application object (as Reto Meier suggests here).
While #foxx1337 suggests android:configChanges="orientation", not only is that answer incomplete, but it is not recommended practice.
Start with android:configChanges="orientation" in your AndroidManifest.xml. Also have a look at Activity restart on rotation Android.
I have an activity that has possibly many different states.
For example
no internet
no license
logged in
not logged in
pending
error
restricted
deprecated
At the moment I have if statements that determine the appropriate state of the application and enable or disable views as required. I was thinking that some sore of STATE pattern might be better.
Can someone give me some idea of how I might do this with an Activity like this? Or in this case is an if statement like this a better option as the views are tightly coupled to the Activity anyway.
I wouldn't disable the views for some of thise things ie no internet. Just let the user try to interact and give relevant error messages.
A good rule of thumb is that if you're changing the views significantly from one state to the other, maybe it should be a different activity? There should be very little reason to change the LAYOUT of views based on state.
This question is as old as the internet now, but the OP should really check out Stateless4J.
It provides lightweight Finite State Machines with easy syntax. I use it in all my Java projects.