Implementing save settings

I am writing some kind of game on Android. And I am wondering how to save the settings so as not to have problems with updates. For example, I save settings with serialization, I have a GameChar class

 public class GameChar implements Serializable{ int health; int damage; Sword sword; } 

But later I decided to add value armor to my game character, I change the class:

 public class GameChar implements Serializable{ int health; int damage; int armor; Sword sword; } 

And now, with the update, I lost all progress because the new GameChar class GameChar not match the GameChar . I have an idea to use Map<String, Object> , where key is the name of the value I save, and the value is any Object I want ( Integer , Float , Calendar or some of my custom Sword class). And I will save this Map file with Serialization .

But if I change some of my custom Sword class, it will not be the same as in my Map , and once again I will lose progress when updating.

Perhaps there is some kind of model or technique that I skip to make it more elegant.

+4
source share
4 answers

Have you noticed that when implementing Serializable you are asked to declare a static long called serialVersionUID ?

The purpose of this variable is to detect older versions of the class during deserialization. An attempt to deserialize a version 1 object from stored data using a version 2 class will throw an exception.

(You can implement this behavior yourself if you are not using Java serialization, it's just a number and if )

Once you find that the saved object is out of date and does not match the current class definition, you can manually fix the problem. For example, if you know that the new member is int a; declared in version 2 , and you select an object serialized by version 1 , you can assign a value that makes sense, despite the lack of information stored in it.

Version tracking is your job, unfortunately. The easiest way is to ensure that a newer version can always be created from the old version without any settings - for example, null will be a significant value.

+2
source

I believe you should take a look at SharedPreferences (this is a kind of map) http://developer.android.com/guide/topics/data/data-storage.html#pref

from your class, I would use it instead of serializing the class at all, just manually save every single item in SharedPreferences and never have any problems with serialization.

0
source

It is important that you are going to check the version of an object as it is deserialized and replace it with an updated version. Check this link

0
source

The β€œtrick” is to overwrite the readObject method and catch an EOFException that occurs if you read in a serialized previous version of GameChar. In the exeption handler, you can set a default value for your reservation. Since this requires declaring transition variables, you also need to overwrite the writeObject method. This example does not contain Sword, which itself must overwrite the readObject and writeObject methods if there are different versions of Sword (the same procedure). In the case of more than two versions, you should use the "version" variable and read objects according to the value of this variable.

 public class GameChar implements Serializable { private static final long serialVersionUID = 12345L; // use serialver to determine UID transient private int health; transient private int damage; transient private int armor; private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { s.writeInt(health); s.writeInt(damage); s.writeInt(armor); } private synchronized void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { health = s.readInt(); damage = s.readInt(); try { armor = s.readInt(); } catch (EOFException eofex) { armor = 999; // default value } } } 

If you use such a version variable, the readObject method might look like this:

 private synchronized void readObject(java.io.ObjectInputStream s) throws IOException { version = s.readInt(); health = s.readInt(); damage = s.readInt(); switch(version) { case 1: armor = 999; // default; break; case 2: armor = s.readInt(); } } 
0
source

All Articles