I want to save application state to be able to restore it after another launch. Is is it better to use method onSaveInstanceState and save it to Bundle or to use SharedPreferences?
Thanks
It depends on your intention. Using the onSaveInstanceState() is only a reasonable solution if you want to ensure saving the state during configurations changes and other restarting events. In case you aim for a true saving of the application's state beyond the lifecycle of the application, you should consider using either the SharedPreferences or maybe even employ a database.
I may not have the same development chops as some of the other posters here (I've been seriously developing apps since July 2012), but I've found a solution that integrates SharedPreferences as well as the onSaveInstanceState().
My App has a splash screen activity that reads values from SharedPreferences and assigns them to the appropriate variables. Additionally, each Activity I make has its own onSaveInstanceState() method, and I commit all of the data I need to save to SharedPreferences there, in each and every Activity. Since onSaveInstanceState() is run before an App or Activity closes normally, it should back up data values under all normal circumstances.
It may not be the most code-efficient solution, especially in larger Apps with many Activities, but as far as my tests go it protects your app from data loss 99% of the time.
If a more experienced developer would like to chime in and confirm or deny this, I'm sure it'll enrich the question and answer.
I am sure onSaveInstanceState() is the better option.
Here it is already given a better explanation: Saving Android Activity state using Save Instance State
Related
I'm trying to save and retrieve my Activity's onSaveInstanceState() when clicking the back button. I have read that by default it is not saved because it is assumed that the user is done with the Activity when clicking back. However, in my app, this is not the case and I would like to call onSaveInstanceState() from within:
#Override
public void onBackPressed() {
super.onBackPressed();
}
It is, however, saved on screen rotation. This I have read is also default behaviour.
I have spent a couple of days trying to hack this, but I'm just not getting anywhere.
I'm trying to save and retrieve my activities savedInstanceState when clicking the back button. I have read that by default it is not saved because it is assumed that the user is done with the activity when clicking back.
All is correct. Moreover, in this case Android assumes the app is no longer needed for user so it can safely terminate the app process.
Can saveInstanceSate be called manually?
Of course. The method is protected. But it doesn't make sense as per your requirement. In your case, even though the "manual" Bundle you pass as a method parameter will be saved by the system, the data residing in RAM will be immediately vanished with the app process itself due to the back press.
It is, however, saved on screen rotation.
Also is correct. In this case Android assumes the app is still in use, so it cares (partially) for restoring its state for you.
However, in my app, this is not the case and I would like to saveInstanceState from within onBackPressed().
I doubt you should struggle the OS idiom. Android provides you alternative options to restore the app state (so a user "thought" he/she got back to your app exactly at the point it was left), e.g. SharedPreferences, database, internal storage etc. I recommend to stick the OS idioms.
I recommend persisting data of this nature and scenario using SharedPreferences. By this, the work of savedInstanceState() is manually done. This data survive untimely app death, configuration change etc.
I've implemented onSaveInstanceState and onRestoreInstanceState in my android activity.
These seem to work OK, but I'd like to explicitly save the instance state when certain things happen (e.g. when the user presses a button) in case the application crashes, or I terminate it via the debugger
I can call the method obviously, but that doesn't provide the correct Bundle or anything else.
I've looked around, but I can't see any way to do this. Is it possible?
If not, can anyone offer a decent solution for saving activity state at specific points in case of crash/termination?
Thanks
Bundles are only stored in memory, which means even if you manage to put the data into the Bundle it will be gone if your app crashes.
I'd suggest you to use onSaveInstanceState for what it's designed for - restoring Activity state within an active process. If you want to persist some information so it won't get lost if the app crashes you should use one of the persistent storage options.
Ideally you would have model class for the data that you are displaying. You can persist the model using SQLite and some DAO library. When you do that you can then restore from the database in onCreate of your Activity.
Depending on complexity of the information you can also choose Shared Preferences. If you have only a few key value pairs this is a good choice and you don't have to use models.
It is said that we can preserve data on Activity's death by overriding onSaveInstanceState(). All data we put there will be saved somewhere in the OS.
My question is - for how long will OS hold that data? Is it predictable at all?
You really shouldn't be thinking about these kinds of things as these are the states of event driven data. The Event is you are transitioning activities and leaving the activity, which will execute the onPause() in which cause you store your data in the onSaveInstanceState() and during the onResume() restore your data from the bundle from onRestoreInstanceState().
If you are TRULY worried about this, then consider storing your data permanently in your app space like SharedPerferences or some local file.
Also a little FYI, if your are thinking about this, have you considered that perhaps what you're doing is bad design?
As usual, it has already been a better discussion: Saving Activity state in Android
In any case, the topic seem to be a controversy since the life span of transient state data is not very well defined, nor can it be predicted.
I want to save some small data structures (~1kB total), as well as the user's preferences, while my app is closed. The settings are modified only in my PreferenceActivity, but the data structures are modified in pretty much every activity. I've extended Application and made all the data structures and preferences static. I've then tried saving to SharedPreferences in my application class's onTerminate() and loading it again in onCreate(). However, onTerminate()'s documentation states that "It will never be called on a production Android device, where processes are removed by simply killing them".
Answers to this question suggest saving to SharedPreferences in the onStop() method of each activity modifying their data. Will this guarantee that the data is saved in all cases? Is there a way to avoid the waste of saving every time the user transitions between activities (or should I even care)?
I would honestly just save in the onPause() of each activity as is recommended by Android (i.e. when you write an email notice how the draft is saved when the app pauses, such as if the screen turns off). Unless you notice that it is causing lags/delays, it probably won't matter too much.
If you do notice lags with this "autosave" method, then you should probably have some sort of "Save" functionality implemented in each activity, which could, for example, entail using a ProgressDialog / AsyncTask combination.
When I want to save some state behavior of the activity, The docs says that we should implement OnSaveInstanceState and OnReceiveInstanceState.
They say that this will save the activity state even after destroy or restarts. I care more about destroy (the activity is completely gone) , does that mean the bundles are considered persistent ?
when I open a pdf reader, clost it and open it again i see that it opens in the same page I was in. is this implemented using Bundles or oth
To store persistent application data use Shared Preferences. Shared Preferences are simply sets of data values that are stored persistently. By persistence, we are talking about data that persists across application lifecycle events. In other words, the application (or device, for that matter) can be started and stopped without losing the data. The next time the user launches the application, that data will still be available.
Some Games use Shared preference for exemple to store the level of the game reached, the player's name ...
see this link to learn how to use Android Preference API
Preference are simular to bundles However they are persistant and bundle are not!!
Keep in mind that if you need to store persistent data you have 4 options to do this:
Using Shared Preferences
Using SQLite Databases
Using Internal Storage
Using External Storage
Bundles are not persistent, the documentation says not to count on it, onSaveInstanceState() is called when the activity is about to be killed by the system, but for a known restart (for
instance on a screen rotation.) If your activity is killed because the system needs more resources (while the
activity is in the background), onSaveInstanceState() will not be called, but onPause() will. onSaveInstanceState()
really is not meant to save persistent data, as the doc states.
You can sorta consider SavedInstanceState() permanent but it's not recommended to use it for saving application related data in a persistent manner as It's not guaranteed to be called and it's not recommended by the authors themselves.
so, Only use them for saving user interface state changes (background color, currently selected items ,..) and use other method for persistence like : SharedPreferences, Files and SQLite.
Bundles are not persistent, and the documentation for them specifies that using them for persistence is not a good idea as their internal format may change between devices or even OS versions.
SharedPreferences, on the other hand, can be persisted and are the recommended way to store information like current app state.
Some relevant parts from SavingActivityState
:
Note: There's no guarantee that onSaveInstanceState() will be called before your activity is destroyed, because there are cases in which it won't be necessary to save the state (such as when the user leaves your activity using the Back button, because the user is explicitly closing the activity).
There is no guarantee data will be stored, especially in the case where your user exits the app.
Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity.
So like K-ballo said, used SharedPreferences if you have persistent data to store. onSavedInstanceState() is mostly useful for storing UI related data.
As every one else has recommended use shared preference and you should do this saving in onDestroy and onSavedInstance both.
When android is going to run low on memory, its just going to kill your application and call your onSavedInstance without calling onDestroy etc. Save your context in bundle it passes in onSavedInstance. When your app comes in foreground again, android will take care of restoring your back stack of activities. But this time it will pass you the bundle in your onCreate for each activity which will have all the values you saved in your onSavedInstance while your app was getting killed.
Hope this helps.
Short answer: It's not permanent.
Long answer: From "Android Programming - The Big Nerd Ranch Guide":
When onSaveInstanceState(...) is called, the data is saved to the
Bundle object. That Bundle object is then stuffed into your activity’s
activity record by the OS
...
So when does the activity record get snuffed? When the user presses
the Back button, your activity really gets destroyed, once and for
all. At that point, your activity record is discarded. Activity
records are also typically discarded on reboot and may also be
discarded if they are not used for a long time.