When does Android's SharedPreferences commit() return false?

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. :)


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.


commit() can return false if there's a problem in saving your data.

Look at the difference between commit() and apply() to get a clearer idea (taken from this site)

apply()

This saves your data into memory immediately and saves the data to disk on a separate thread. So there is no chance of blocking the main thread (your app won’t hang).

It is the preferred technique but has only been available since Gingerbread (API 9, Android 2.3).

commit()

Calling this will save the data to the file however, the process is carried out in the thread that called it, stopping everything else until the save is complete. It returns true on successful completion, false on failure.

Use commit() if you need confirmation of the success of saving your data or if you are developing for pre-Gingerbread devices. commit() has been available since API 1