I know saveInstanceState() is used to store activity variables, text in EditText, etc.
But I have a doubt that should I save state of view?
Let me give you a scenario. My view has 3 buttons. On clicking one of them, a WebView is displayed to user (in same activity). Now if app gets killed, should I save state that user was displayed WebView when app got killed and when activity gets recreated display WebView instead of buttons?
Other scenario is, I have 3 tabs in view. Selecting each tab shows different view. As explained in above case again should I save that user has last selected this tab?
It will be best if you can explain the cases where I should and should not save activity state.
The operating system knows when it should re-create your app's previous state (the screen orientation changed or your app was killed in the background by the OS) and when to create a new instance (the user left your app with the back button). The onRestoreInstanceState() method is only called when there's a state to restore (when the system is restoring a previous state, as opposed to creating a new instance of the activity).
The short answer, then, is that if you override onSaveInstanceState() and onRestoreInstanceState(), the system will call them when appropriate, and you don't have to worry about deciding when you "should" save state.
When overriding onSaveInstanceState(), yes, you should save everything about your activity's state. This is the method being used during screen orientation change. Think about it - if you rotate your phone, do you expect the current app to change tabs, or the screen that just opened to disappear?
For more information, see the Android documentation on recreating an activity.
I have not done very much research on savedIntanceState on app gets killed. But yes you may save maybe a integer variable (referring to which button is clicked) in state, so that when activity is recreated, you know which webview used to be shown (or none). Same goes to your second situation.
Some extra use case of saved instance state:
One of the most used scenario is during user switches orientation, say you have a couple of edit texts on screen, their holding texts would be gone if user change his device orientation. Saved instance state helps you to recover the entered texts.
Another situation is you will most likely have a few class variable in your activity, probably used to save what user has done, or some temporary list object in a list activity. Saving those variables also prevents you from needing to recover the data on orientation change.
Related
I have an activity with 4 elements. A spinner containing a list of dates, a spinner containing a list of hours, a button and a list view. The spinner's selected items are used to form a web service URL which is called when the button is clicked and the response is shown in the list view.
The issue is if the user views the app in portrait mode, chooses a date, chooses an hour and clicks the button, the response of the web service call is shown in the list view however, if the device is rotated to landscape then the data in the list view is gone (because in order to get it there a button click is needed).
I understand that onCreate is called when the screen is rotated. I do not want to force the orientation so is there any way I can stop the list view being cleared? Note that the selected values in my spinners remain the same after rotation, it is just the response in the list view that is lost.
Simplest way to prevent activity recreation put this in you AndroidManifest
<activity android:name=".YourActivityName"
android:configChanges="orientation|keyboardHidden|screenSize">
Read this for more info - Supporting Multiple Screens
You can force activity screen orientation in AndroidManifest.xml by setting screenOrientation property:
<activity android:name=".FooActivity"
android:screenOrientation="portrait"/>
This is a half-solution. If you want to handle screen rotation, you should save and restore activity state. This is the major, royal PITA in any Android application I've seen.
The problem is, that your application logic is mixed with view code, which can be destroyed at any moment. Perfect combination, Google! It's like running a function that can disappear during execution. :)
To counter this sorry design decision you may want to move your application logic to service, which will not be destroyed when screen rotates. This 2-layer design is closer to universally accepted MVC pattern, as you separate your logic from your view. Service stays, activity attaches and detaches from service on demand, making screen rotation handling a breeze.
If you're dealing with webservices, do not try to invent your own solution for this. There is couple of nice libraries to handle this nicely, such as RoboSpice and you'll probably never come with any quick solution that is as good as those libs. Give it a try.
Also, watch this Google I/O video about developing Android REST client applications: https://www.youtube.com/watch?v=xHXn3Kg2IQE
Have your button set a static class variable, or shared preference. Then, call a method that reads that value, and does what you want. THEN, put a call to that same method, in onResume(), possibly based on a condition... I think that's what's worked for me. When you come back from configuration change or kill, onResume() should re-do whatever you had last done.
In my app I am creating a custom preference screen. This screen in reached via mainActivity (launcher). The mainActivity also shows the current status of some of these settings by reading them and laying them on views. Now, when the user will reach one of the preference screens and edit them, by design I aim to bring him back to the mainActivity (it would be intuitive to press the back button). This time however I want to show the latest edited settings.
I am used to putting layout operations in onCreate. But, in this case onCreate will only be called once when the activity starts and read the status of preference settings and lay them on screen. However, when he will open a settings activity, edit them and press back button he will not see his latest settings laid on screen as onCreate need not be called.
So, on what activity callback should I place the operations to read preferences and lay them on views.
This is based on my understanding and I may have messed up big time. Guide me, Thanks...
To anyone looking for an answer. Its pretty basic stuff. Create function in your main activity to read preferences and update your views. Now, start your preference activity using startActivityforResult() and when result arrives from that activity, run the same function inside onActivityResult(). Done.
When app is running, users adds some views in the Layout. I want to store this Layout, so that when i reopen the app it should return the same state.
How can I achieve that?
Use onSaveInstanceState() and onRestoreInstanceState() callbacks to save and restore your views.
More at Managing the Activity Lifecycle and Recreating an Activity.
[EDIT] - As per #kadatt comment.
I think what you are trying to do is possible duplicate of android-saving-state-of-dynamically-changed-layout.
I dont think there is any standard way of doing this. You will have to implement your own functionality to save state of dynamic UI in some form which can be loaded again.
In the main activity of my app, I have three tabs which, when clicked, switch the contentView of the activity to a different layout. My problem is that when the orientation changes, the first tab is automatically selected and loads the first layout.
My first thought on how to fix this would be to just save the tab location in the savedInstanceState or a sharedPrefs file, but the problem with one of these solutions is that they will also happen when the app is first opened and OnCreate() is called.
To be clear, I want the following to happen:
On App load (fresh activity, onCreate() called)- Load first tab
always
On App resume (after app paused, Onresume() called)-Load last opened tab
On orientation change(after change, OnCreate() called?)- Load last opened tab
Basically I am trying to find a way to distinguish between an orientation change (witch calls OnDestroy() and onCreate()) and the onCreate() and onDestory() when the app is first launched.
If its possible, I'd rather not but the configChanges="orientation" line in my manifest, and handle the switch myself, because I've heard that can cause problems when dealing with different screen sizes and densities, etc.
Is there any way to accomplish this, or do I have to settle for a different behavior?
onSaveInstanceState is the right way to go. It will not persist after the activity has been finished, only when it's "going to a background state" or doing an orientation change.
i am new to android.i have one single activity with main.xml file. Now, i have one scroll view in that main.xml file.when i run my application in portrait mode and when i go to the bottom of the scroll view and than when i change my application state to the landscape mode than i go to the top of the scroll view..that means when we switch between portrait to landscape or vice versa the activity is recalled. so need to save the application state in portrait and restore in landscape. so any solution of it?
thanks in advance
Aamirkhan I.
The documentation does a decent job of explaining different ways to handle configuration changes, including screen orientation changes. One of those methods, which is good for saving temporary state of the UI, is saving data in the onSavedInstanceState() method--as #Jason Kuang mentioned.
Generally, you can rely on Android to save and restore the state of Views without any special effort on your part. The source code for the protected method onSaveInstanceState() explains (emphasis added):
The default implementation takes care of most of the UI per-instance state for you by calling android.view.View.onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(android.os.Bundle)). If you override this method to save additional information not captured by each individual view, you will likely want to call through to the default implementation, otherwise be prepared to save all of the state of each view yourself.
This is a little deceptive, because the API documentation states that EditTexts and TextViews must have android:freezesText="true" explicitly declared on them in your layout XML files to ensure that Android automatically stores their state when onSaveInstanceState() is invoked. I have not tested this recently, but it is what the source code seems to be doing. Therefore, handling temporary UI state on your own is best.
Another tip: You can explicitly prevent the storage of temporary data for a View by calling setSaveEnabled(false) on that View. (This will not affect its children.)
As a rule, it's a good idea to manually save the on-screen state in your onPause() method, and also in onSaveInstanceState().