4

我正在android上写一种游戏。我想知道如何保存设置以免更新出现问题。例如我用序列化保存设置,我有类GameChar

public class GameChar implements Serializable{

  int health;
  int damage;

  Sword sword;
}

但后来我决定为我的游戏角色添加价值盔甲,我改变了职业:

public class GameChar implements Serializable{

  int health;
  int damage;

  int armor;

  Sword sword;
}

现在随着更新,我失去了所有进展,因为新课程GameCharGameChar. 我有一个想法,其中键是我保存的值的名称,Map<String, Object>值是Object我想要的任何值(Integer,,或一些我的用户类FloatCalendarSword)。我将把它保存Map到文件中Serialization

但是如果我改变我的一些用户类Sword,它将与我的用户类不同,Map并且我将再次失去更新进度。

也许有一些我想念的模式或技术使它更优雅。

4

4 回答 4

2

您是否注意到,在实施时Serializable,您被要求声明一个static long被调用的serialVersionUID

此变量的目的是在反序列化时检测 Class 的旧版本。尝试1使用版本类从保存的数据中反序列化版本对象2将导致异常。

(你可以自己实现这个行为,如果你不使用 Java 的序列化工具,它只是一个数字和一个if

一旦您检测到您保存的对象已过时,并且与当前的类定义不匹配,您就可以手动修复该问题。例如,如果您知道int a;在 version 中声明了一个新成员2,并且您选择了一个使用 version 序列化的对象1,您可以分配一个有意义的值,尽管在保存的信息中丢失了。

不幸的是,跟踪版本是您的工作。解决此问题的最简单方法是确保始终可以从旧版本实例化新版本而无需调整——例如,具有null有意义的值。

于 2013-04-02T13:07:43.057 回答
0

“诀窍”是覆盖 readObject 方法并捕获在您读取 GameChar 的序列化先前版本时发生的 EOFException。在异常处理程序中,您可以为 Armor 然后分配一个默认值。由于这需要声明变量瞬态,您还需要覆盖 writeObject 方法。此示例不包含 Sword,如果 Sword 有不同版本(相同过程),它本身应该覆盖 readObject 和 writeObject 方法。如果版本超过 2 个,则应使用变量“版本”并根据该变量的值读取对象。

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
    }
}
}

如果您使用这样的“版本”变量,readObject 方法可能如下所示:

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();
    }
}
于 2013-04-02T13:39:46.280 回答
0

我认为你应该看看 SharedPreferences (这是一种地图) http://developer.android.com/guide/topics/data/data-storage.html#pref

从您的示例类中,我将使用它并且根本不序列化该类,只需将每个单独的项目手动保存到 SharedPreferences 中,并且永远不会有任何序列化问题。

于 2013-04-02T13:05:23.223 回答
0

本质上,您将在反序列化对象时检查对象的版本并将其替换为更新的版本。检查此链接

于 2013-04-02T13:07:33.837 回答