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.
Related
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)
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.
hey people,
I have almost finished writing my first android app. It is a note taking app with add, edit view screens etc...
Initially I was handling moving between screens in a single activity by creating new layout objects such as tables etc... and displaying them.
However after some more reading I have changed my method of moving between screens by using different activities for different screens. However each activity that is called as an intent retrieves a large number of variables from the main activity via setExtra and passes back a large number of variables as well.
Now I want my app to be as efficient as possible and I personally think that handling it all in one activity is less memory hungry and processor intensive although this has the negative of meaning variables are always present (and consuming memory) unlink in a separate activity where they are killed on finish().
But you guys are more knowledgeable then me so what do you think is the best way to do it?
If you launch a new activity for the new screens then you will add that activity to the stack. That way a user can press back and get back to the previous activity. Just changing the layout removes this functionality. I doubt very much you'll have performance issues either way.
Best practice would be to start a new activity, best performance might be to use your current approach.
All your activities will reside and run from the same process. So there is no reason you need to pass around a pile of variables. You could (for example) stick them in a singleton which represents your context. When one activity hands over to another it fills in the singleton and the next one picks up its data from there.
Of course if you ever intend an external activity to interact with your ones you may have to rethink this approach, but I think you'd be fine to keep your views as separate activities. Even if memory is ever so slightly higher, I think it's better to do things correctly and only worry about optimization if and only when it becomes obvious you need it.
I have a simple game
It displays a list of items that the user selects from with game timer.
I am using native Android widgets in an Activity and a Service to control the game. This has turned out to be cumbersome and my Activity is getting bloated and difficult to maintain.
I have a timer (currently I am using a count down timer)
I need to keep track of scores and rounds
I need to restore the state when the game changes orientation
I need to access a database.
I need different states in the game (buttons cannot be pressed, and sometimes they can)
I need to pull as much out of the Activity as I can
I don't need a canvas, but can someone suggest the best pattern I could use for this? What are the main classes I would have, do I need a game thread etc.
Well, you should have an activity for each level. All of the basic information should be in this activity as variables, the score, level, time, state, etc. You'll need to find a way to put all of them into a bundle when the application closes, and pull all of them out of the bundle when it re-opens. Should be fairly straight-forward.
As for orientation changes, I would lock it to one orientation for now, and get the game working. If it can resume state, then it should be able to handle an orientation change, but to make life simpler at first, I recommend you lock the orientation.
Hope this helps!