StackOverflow programming & SharedPreferences Editor commit

SharedPreferences Editor commit() will block your UI thread. Better use apply() when possible.
Read more here: Srool The Knife: StackOverflow Programming

Interesting. libGDX uses commit by the way. I will let them know about this article, maybe they can fix it.

Practically speaking though the commit() is reasonably fast - and saves you from having to wonder if there are “race conditions” (for example if the changes were written and if you maybe reading from them later - before they are fully written).

Using apply() would not slow you down (by the slowness of an SD card write) - but you lose confidence if the data actually gets written “soon”.

Or just write a wrapper for sharedprefs that caches all the data locally in an instance held by the application and use an Executer to save it all on exit.

This way you get to do other cool things like marshal ArrayList<thing> to json and back so you can save it…

Read the documentation carefully, and you will see that you should not worry about concurrency or race condition issues. As for the difference in speed - I actually tested before I went on to write about it. In one case it was blocking for over a second. It might as well be because of other things going on, but why would you block the UI thread, if all is needed from you is to use apply??

Better to use your time more productively… someone already wrote the code to cache and handle saving the data…

Ok, thanks to critique about my comments above - I am considering replacing all commit() in my app with apply().

It seems the calls to commit() and apply() are atomic (i.e. no issue of race-condition where parts of one call are intermixed with other leading to confusion about the final result).

In any case, even with apply() the value is written IMMEDIATELY to in-memory/RAM version of the Shared Preferences - so if they are queries they SHOULD return the newly written value.

The ONLY caveat I could find is a post that mirrors my own concerns in above thread - the poster suggests that he saw his writes using apply() lost due to system killing the app to reclaim resources.

android - What’s the difference between commit() and apply() - Stack Overflow

QUOTE:

I’m experiencing some problems using apply() instead commit(). As stated before in other responses, the apply() is asynchronous. I’m getting the problem that the changes formed to a “string set” preference are never written to the persistent memory.

It happens if you “force detention” of the program or, in the ROM that I have installed on my device with Android 4.1, when the process is killed by the system due to memory necessities.

I recommend to use “commit()” instead “apply()” if you want your preferences alive.

answered Dec 17 '12 at 8:41
JoseLSegura

So while android documentation suggests that commit()/apply() are safe from the android lifecycle - is the Force Close to reclaim resources a separate issue to think about ?

If so, this would mean if you switch away from an app while it is still synching some long set of data - you could lose that info. Meanwhile with commit() - it would just make the app unresponsive until it’s done. On the other hand TOO long an unresponsive app could be killed also (i.e. does this equalize the threat - as commit() is as vulnerable then ?).

It depends on just HOW lazy android is about committing the apply() in RAM finally to the SD card … ?

Most other posts on stackoverflow mirror the android documentation rule of thumb:

  • as long as you are not using the return value from commit() - you can safely replace all commit() by apply()

Other caveat is that apply() is only available on Android 2.3 - so should use a conditional using Build.VERSION_CODES.GINGERBREAD:

Rungeek.com - Bernie’s Blog
Android’s Shared Preferences: Commit to Apply



SharedPreferences preferences = getPreferences(MODE_PRIVATE);
Editor editor = preferences.edit();
editor.putBoolean("MY_KEY", true);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
	editor.commit();
} else {
	editor.apply();
}	


Sure… who ? Certainly not the Android framework guys. You can only store basic int/string/etc in SharedPreferences unless you want to limit the code to only new versions of Android.