This is more of a request for your opinion in something, rather than a question. It will be kinda long, so no worries if you don’t have the patience to read it all. Stop here if you don’t 🙂
I am currently using Shared Preferences to frequently store some values, one by one, during the execution of my app. In fact, every 2 seconds the values change and they need to be stored in the preferences so the user, after closing the app and reopening it, can continue from where he left off.
A problem which I’ve thought of is that if by any chance the app is closed forcefully, for example the battery dies WHILE the values are being saved, then when the user tries to resume from where he left off, the data won’t be valid, as it wasn’t previously entirely saved.(for example just 2 out of 5 values managed to be stored).
How i thought to overcome this problem is to save the data twice, in “TWO SLOTS” (what i mean by slot is each value, like I’ve said there are multiple values, will be stored in either “valueName_1” or “valueName_2”), and alongside the normal values stores, i’ll also save two values inside the preferences which will be used to validate if the data was entirely saved or not.
One of these two values curSavingSpot will refer to the position in one of those two slots where I’ve LAST saved (or have TRIED to save in case of fail) the values, and the other curSavedSuccessfully will keep track if the LAST stored values were ALL stores successfully.
For example:
- initially every field in the Shared Pref is null.
curSavingSpotpoints to 1 (the first “slot”) andcurSavedSuccessfullyis false. -
i start saving the values in slot 1 and finish saving them without any interruptions, so
curSavedSuccessfullywill be made true as we have successfully saved all values -
after 2 seconds, i start saving the new values. This time in slot 2. But first, i set the
curSavingSpotvalue to 2 ANDcurSavedSuccessfullyto false. Let’s say when i save 3 out of 5 values (got 2 more to go), the device crashes. When i reboot it, i’ll first check to see if the last saving session finished successfully, according tocurSavedSuccessfullythat didn’t happen, so i look atcurSavingSpotand take the opposite value, in this case i know 2 hasn’t finished successfully, so it means 1 has correct values.
What do you think? Is this a good way to do this? Is there a better way to make sure it has saved all the required values?
Any suggestions? Are there any flaws with this idea?
Sorry for the long post.
Honestly it sounds to me like you are overthinking it. The commit() and apply() methods of SharedPreferences claim to be atomic, this means either all the changes to SharedPreferences happen or none of them do. As long as you are not calling commit() more than once (after you have made all your changes) you should be fine. Basically your scenario where you can commit only some of the preferences will never happen. If your values are invalid when commited individually, it makes no sense to commit them one by one, just commit them when they are all ready to be commited.
You could also use a DB if you want to audit your commits (and always just pick the one with the last timestamp). SQLite has atomic commits, and you can read more about what an atomic commit means here and why it never writes just part of a row.