As far as I know onSaveInstanceState is called every time the app goes to background. If so then the app might still execute some code while it is in the background. So, I'm wondering what will happen if the state of variable x will be saved during onSaveInstanceState, the app will still continue execution in the background and will change the value of the variable x. A little bit later the process will be killed and the activity will be recreated (when the user will come back to app).
So, what would be the value of x? It seems that it will have an old value(saved during onSaveInstanceState), but what will happen to the new value, will it be lost?
First of all the variables as you call them are not automatically saved you need to put them in a Bundle, similar to when you add Extras to an Intent.
And retrieve those values taking them out of the Bundle in the method onRestoreInstanceState. So the value of a certain variable, when restored would be the one you set in the Bundle if you later change that value and not put it on the Bundle it will be lost.
Also please take into account that this background execution as you called it, it is not so. It is just a minimal code execution to save the state of your activity not an actual background execution
Related
I have come across 2 different types to get my activity running based on some params. The first one is savedInstanceState and the other is getIntent.getExtras()
Q1)
So what I don't understand is, once I pass bundle to my activity and then start it, it should have the bundle.
But, if for some reason the activity is recreated again, it should have the same bundle all over again. (am I right?)
Q2) Based on the fact that Q1 is true, and the fact that I can't just override the bundle once the activity already started, I guess that if for some reason in my already started Activity, I want to change some params of the bundle, I should create some activity fields and used those fields in my activity life.
And override saveInstanseState to save the new fields if from some reason my activity would be recreated. is it true?
Q3) Based on the fact that all above is true, in onCreate() should every activity in world of Android need to start like this:
if (savedInstanceState != null) {
mType = savedInstanceState.getInt("some_val1");
mCardId = savedInstanceState.getLong("some_val2");
mQuery = savedInstanceState.getString("some_val3");
mCategory = savedInstanceState.getLong("some_val4");;
} else {
mType = getIntent().getExtras().getInt("some_val1");
mCardId = getIntent().getExtras().getLong("some_val2");
mQuery = getIntent().getExtras().getString("some_val3");
mCategory = getIntent().getExtras().getString("some_val4");
}
Q4) Assume onSaveInstanceState was called and saved values that are different from the original bundle who started the activity (the getIntent.getExtras), If the activity is recreated again, does this mean that saveInstanceState is different from the getIntent.getExtras() or they are now the same? (If they are the same, then the if/else on the code above has no true meaning, cause it is the same!).
Q5) If I didn't override the onSaveInstanceState but when I created the activity I pass it a Bundle, does this still mean that I can get my original bundle if the activity recreated again? ( i guess this question will answer itself based on other answers)
The main difference between getIntent().getExtras() and the savedInstanceState is that they have different usages. The intent is for the communication between activities while the saved state is for the current state of your UI when you leave your activity e.g. by pressing the home button. So it will been saved the position of your ListViews and similar or the value of unsaved TextEdits.
Q1: Yes in general that information should not been lost, as long you don't open the activity a second time.
Q2: True so far. The default views will save their state so you don't need to do it yourself. However if your Activity is started a second time with a different bundle you will have the new values.
Q3: No not necessary, that depends on your use case, however that would not break anything. The point is when you load date from the internet you would have to wait just one time, on the second onCreate() call the data will been restored (if you show them in UI elements with an id!).
Q4: The intent would be the initial value while the saved state is the modified state of the values.
Q5: In general that should work the same. Since the basic ui elements will save their state by default.
The point of the saved state is to keep ui changes even if your app was destroyed in the background. So your app will resume at that point where left it even if it was not anymore in the memory of your device.
In my application, an activity A calls the activity B (via an explicit intent). Lifecycle, B may get killed and recreated etc.
When B is called (from A) it initializes some things. But when recreated it needs to just pick up from where it left. It will finish() some time, then I'm back to A, which might later call B again...
B needs to save a very small amount of data, usually just a few int values. (The rest that I need to restore it is in getIntent() which seems to be still there after the activity has been killed and recreated.) I've heard that onSaveInstanceState and onRestoreInstanceState are expensive and that they are not guaranteed. Plus, I don't need to save the state of views. (For that reason, should I override these two methods with blank ones, preventing the parent ones to get called?)
What's the efficient way to store just a few int values? Should I store the values as static fields of the activity B itself, or of the application itself, or of another class written just for that?
Also, how does the activity B know whether it's been recreated rather than called?
I've heard that onSaveInstanceState and onRestoreInstanceState are expensive and that they are not guaranteed.
They are not particularly expensive. And, for your scenario, they will be used most of the time. The exception would be if your task is not being restarted, such as:
the user got rid of your task by swiping it off the recent-tasks list
at least pre-Android 5.0, your app has not be run in ages and falls off the end of the recent-tasks list
the user force-stops you from Settings
But in those cases you will not be restarting at B, since I assume B is not your launcher activity.
For that reason, should I override these two methods with blank ones, preventing the parent ones to get called?
Not unless you are experiencing actual problems, not just rumors of hints of potential problems.
What's the efficient way to store just a few int values?
For your case, probably use the saved instance state Bundle.
If you cannot afford to lose those values even if your task goes away (and you will not be restarting at anyway), store them in a file, database, or SharedPreferences.
Should I store the values as static fields of the activity B itself, or of the application itself, or of another class written just for that?
No, because none of those will work. You specifically state that your concern is "Lifecycle, B may get killed and recreated etc.". Part of that lifecycle is that your process may be terminated, and in that case, static data members go "poof".
Also, how does the activity B know whether it's been recreated rather than called?
See if the saved instance state Bundle passed into onCreate() is not null. Or, see if a retained fragment exists, if you're using one of those.
In my application I have a filter function on table view which give filtered result in table. I set filtered options(checkboxes) in shared preferences so the next time the user go in filter screen it sees the checkboxes checked so it know what was the table filtered for and what he did check last time for filtering.
when the application launches i set them all to unchecked(requirement), but i dont know when the application is launched or resume. when the application is resumed from memory it again initialized all my data types. how can i check the application is resumed. if i set things in activity onResume - no gain it is called every time i just want to know only when the application is resumed.
What happens now i dont know when the application is resumed from memory, my filter behaves like application launched and set all to unchecked
what i did is, on my first activity made a boolean and put false and stored it in shared preferences, then did it true when start that filtering thing. so it remains true as the application remains in the memory and resume even. when application exits, and the launched again on startup it again turns false
There's no "resumed from memory" state. It is either resumed or created (or restarted). So you should rework your application logic and init your stuff on onCreate() instead of onResume()
I am not able to understand you question properly, but as far as my understanding goes, you are filtering user options through shared preferences. If this is so, you need not unset/set each option programatically. Android remembers and and restores this for you. If you want to access these, just call context.getSharedPreferences() and from sharedPreferences object received call getBoolean (key,defValue).
You can restore your checkboxes on onRestart(), that means your activity was not killed and is resumed after it had been stopped(either manually or by android).
I have a text field which indicates date selected by the user.Also i have provided a button for the user to change the currect date.
The problem i am facing is as follows.
1 . In the Oncreate method i have set the textfield to the current date.When the activity gets created it displays the current date.
I use the button and change the date to someother date.
All this works fine..
But when i rotate the device the oncreate again gets called and textfield gets changed to the current one. I want the textfield to retain the user selected one.
Please help me in this issue. Is there any way to prevent this ?
Screen rotation kills your activity and causes the entire lifecycle to restart. When this happens, onCreate will still have access to the original intent which began the activity, and certain widgets may retain some of their state (EditTexts, for example), but much of your dynamic Activity data will be lost. To prevent this, look into using the onSaveInstanceState method. This will allow you to put any important data members into a Bundle before rotation kills the screen. This Bundle is then passed to your onCreate as the parameter savedInstanceState. Here are the dev documents on this:
http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState%28android.os.Bundle%29
In your case, you'll want to save your date value by putting it onto the Bundle as an extra. Then, in onCreate, check if savedInstanceState is not null, indicating that it contains your date and handled it accordingly. Also, make sure that if you set a default value for this text later on in the Activity Lifecycle, it does not clobber your retrieved date.
You need to save the variable before rotation. I think that the best option is use the Application class as a place to save variable and do it in onPause() function.
Does anyone know of an exhaustive list of when the savedInstanceState bundle will be used in an activity?
I know it's used when the device orientation changes. However, it doesn't seem to be used when the user force closes the app from the Android settings, but this might be due to something in my code.
What other cases are there?
To be clear, by "used" I mean when onCreate() is called, the savedInstanceState bundle is not null and contains the data I passed into it the last time onSaveInstanceState() was called.
It's used when the Activity is forcefully terminated by the OS (ex: when your Activity is in the background and another task needs resources). When this happens, onSaveInstanceState(Bundle outstate) will be called and it's up to your app to add any state data you want to save in outstate.
When the user resumes your Activity, onCreate(Bundle savedInstanceState) gets called and savedInstanceState will be non-null if your Activity was terminated in a scenario described above. Your app can then grab the data from savedInstanceState and regenerate your Activity's state to how it was when the user last saw it.
Basically in onCreate, when savedInstanceState is null, then it means this is a 'fresh' launch of your Activity. And when it's non-null (if your app saved the data in onSaveInstanceState(...), it means the Activity state needs to be recreated.
onSaveInstanceState is used to store data only for application lifetime (i.e. temporarily)
The data is held in memory only until the application is alive, in other words this data is lost when the application closes, so in your case when you force close the app onSaveInstanceState is not used.
It can only be called when you do operations while your application is still alive, for e.g. when you change the screen orientation the activity is still intact so onSaveInstanceState is called.
However if you want to permanently store the data you would have to use SharedPreferences and SQLite database.