In my app, I'm storing some data in SharedPreferences
- it works as needed.
Now I want to create log messages for some incorrect situations.
I successfully handle situations where the preferences are empty or they throw some exception while loading.
The only error that can show up while saving values is commit()
returning false
- I don't know why this could happen and what I should do in that case.
So my question is:
When does the commit()
method return false
?
And what should I do in that case?
Could a possible solution be to call commit()
again and again (something like while (!editor.commit()) {}
)?
Unlike commit(), which writes its preferences out to persistent storage synchronously, apply() commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won't be notified of any failures.
To clear all the values in the shared preferences file, call the clear() method on the shared preferences editor and apply the changes. SharedPreferences.
A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared. This page shows you how to use the SharedPreferences APIs to store and retrieve simple values.
Android Shared Preferences Project Code The MainActivity. java file is used to save and retrieve the data through keys.
First, you would never want to do:
while(!editor.commit()) {;}
. If you want to retry a commit you would do so a handful of times rather than loop forever.
Regarding when commit() returns -1: Both commit() and apply() make the changes to memory and then make the calls to write the changes to disk (per source). commit() waits for the disk write to return to return the results. So the answer to your question is: "When saving the preference state to disk fails for your particular commit() call." Since changes were reflected in memory they may or may not be written to disk by another commit() or apply() call before or after your attempted disk write (think racing threads). Since there isn't code to rollback the memory update and SharedPreferences are singletons (per source) other components in your app will see your changes even if they didn't save to disk.
In summary, looping a few times (not forever) to ensure a commit() writes to disk seems fine to get you past an intermitten I/O issue, but it would be a rare I/O-based situation that it fails. If you need perfect commit scope you would want to re-read the disk to validate each commit() call which has performance implications and is overkill for all but a small set of situations.
And can while(!editor.commit()) {;} be solution for success anyway?
'commit' operation is synchronous and performed on the UI thread, thus, if you have some unrecoverable error which occurs every time you try to perform commit
, you'll block your entire UI thread with this code and user will see ANR. Not good.
'apply', on the other hand, is asynchronous, thus it can't block UI thread even if you will perform it indefinitely long.
Documentation says very little about the possible failures of the 'commit' operation (take a look here here, here and there). The preferences are stored inside the xml file stored on your internal storage, so one possible failure can be the corrupted xml file. The second one can be found in documentation:
Note that when two editors are modifying preferences at the same time, the last one to call commit wins.
There is little you can do about the corrupted file, and, well, don't try to modify preferences from different places at the same time. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With