24

Some of the users of my application complain that sometimes (in a random way) the settings of my application are getting reverted to their default state (usually after a reboot of the phone). I never managed to reproduce the problem though. I am thinking it is due to the fact that in many places in my app I have a piece of code that calls the shared preferences editor and commits changes - Can it resolves in corrupting the shared preference file if I try to commit several changes to the same preference file at the same time? (Multi-thread application)

I am really lost. I tried to look in the web for hours to find a solution without a success.

If anyone has even an idea so I can start investigating, I would be grateful.

Thanks, Amit Moran

Amit Moran
  • 285
  • 1
  • 2
  • 8
  • Synchronizing the commits would be a first approach. – Kirill Rakhman Oct 30 '11 at 12:10
  • Maybe you were writing a null key at some point - this would clear the preferences when you try to load them - see : http://stackoverflow.com/questions/5368442/android-getsharedpreferences-error-map-value-without-name-attribute-boolean/19621603#19621603 – Mr_and_Mrs_D Oct 30 '13 at 15:49

5 Answers5

17

I'd echo the other answers - that you need to avoid conflicts if you don't want to corrupt the file - and I'd go further to suggest that you're probably misuing SharedPreferences.

SPs are designed to store small pieces of information about your app - user settings like volume or whether music is playing or things like that.

SPs are NOT designed for storing data which changes often and/or large amounts of data and it's a bad idea to try to do this (for the reasons you've discovered and a few others).

Remember that SPs are really just an XML file - you're incurring the overhead of parsing and recreating that every time you change it too!

The idea of an App which updates SPs in more than one thread is a bit mad I think - you need a better way of managing and storing the data you're saving - it will pay-off for you in more than one way...

  • I guess you are right. I guess I should use some other way (like SQLite) for high frequency changes. I'll give it a try. – Amit Moran Nov 02 '11 at 14:05
  • OK, so I tested it. To do that, I have isolated the settings that change repeatedly and put them in their own Shared Preferences file. So this way the user more "stable" preferences file is not used all the time. It seems to solve the problem. (I'm still testing it but so far so good). What would you suggest to use as an alternative to the shared preferences when I want to save data across app lunches? ( SQLite DB will get less quickly corrupted? ) – Amit Moran Nov 11 '11 at 06:33
  • 9
    If I were changing settings/data a lot, I'd hold the data in memory (in an Object in the Activity Class or similar) and only save it (to SharedPreferences or a Database or whatever) in onPause() There's really no advantage to writing data to the phone frequently - it's often VERY slow (esp writing to SD Card) - just make sure it's written if the App is paused or whatever... –  Nov 13 '11 at 00:08
6

According to the SharedPreferences.Editor documentation:

Note that when two editors are modifying preferences at the same time, the last one to call commit wins.

From this I gather that multiple simultaneous commits will not wipe out your preferences, but it's possible that not all changes you are attempting to write will end up getting written if multiple Editor instances are being used simultaneously. To avoid this you could put all preference modifications in synchronized blocks or even use one synchronized static method for all preference writing.

goto10
  • 4,370
  • 1
  • 22
  • 33
  • 3
    Yea, I saw this documentation. My problem is that all preferences revert to default, not that some are not saved... – Amit Moran Nov 02 '11 at 14:02
1

I suggest you use a singleton to manage the preferences. Whether you do this by implementing a true java singleton, or by using Android's Application Context is up to you. (see this question for several good arguments for/against each)

For something like SharedPreferences, this is a good way to manage them especially for a multi-thread application. This will possibly eliminate some of the questioning of whether or not the commits are conflicting with each other. This may not be the whole problem, but it's somewhere to start.

Community
  • 1
  • 1
WilHall
  • 11,644
  • 6
  • 31
  • 53
0

I found I was losing a particular entry in SharedPreferences by opening the editor, doing a getString on it, and then committing without doing a putString on the entry first, even if there was no required change. Once I stubbed in a putString to save the value no matter what, the entry stopped vanishing after the commit.

rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
saswanb
  • 1,975
  • 1
  • 17
  • 25
0

I had a similar problem: my preferences had not been saved reliably. On some devices (in my case the XOOM-Tablet) data got sometimes lost and sometimes not. I've solved the problem by simply calling clear() on the editor before commiting new data.

Shared Preferences get lost after shutting down device or killing the app

Community
  • 1
  • 1
Chris
  • 4,403
  • 4
  • 42
  • 54