java - 将可序列化对象保存在持久存储中(android)

标签 java android serialization persistent-storage

我需要在持久性存储中存储一个复杂的自定义对象,以便在我的应用中保存用户的游戏进度。该对象和该对象中的每个对象都实现了 Serializable

我调用使用加载和保存方法在 Activity 之间传递对象。我还调用了 Save 方法 onStop() 来在应用程序关闭/销毁时保存对象。它工作正常。

 public static Game Load(Context context){
    try{
        FileInputStream fis = context.openFileInput("player1.data");
        ObjectInputStream is = new ObjectInputStream(fis);
        Game game = (Game) is.readObject();
        is.close();
        fis.close();
        return game;
    }catch (Exception e){
        Log.e("#Load", "creating new game - \n" + e.toString());
        Game newGame = new Game();
        return newGame;
    }
}


public static void Save(Context context,Game game){
    try{
        FileOutputStream fos = context.getApplicationContext().openFileOutput("player1.data", Context.MODE_PRIVATE);
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(game);
        os.close();
        fos.close();
    }catch (Exception e){
        Log.e("#Save", "Failed to save - \n" + e.toString());
    }
}

但是,如果应用程序被强制关闭或关闭并销毁,Game 对象就会变得困惑。重新启动时,应用程序将加载保存在 onStop() 中的 game,但是当 game 对象被用户更改/交互时通过该应用程序,我的应用程序强制关闭,并在手机屏幕上显示“意外停止”消息。通过查看日志,我知道当 Game 对象在强制关闭/销毁后在启动时加载时,Load 方法返回 game 而不是 newGame,因此强制关闭之间的保存/加载过程以某种方式搞砸了。

在日志中,我看到了这个:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

因此,我被引导相信使用 Serializable 时发生了一些奇怪的事情,或者我错误地写入了持久性存储。

我的问题:您是否发现我的代码存在任何根本性错误? (请记住,此代码确实有效,只是在 Force Close 情况下不起作用)

有人告诉我为了我的目的考虑使用 gson/JSON (?);这种方法会比 Serializable 有更好的结果吗?我该如何使用它?

更新:似乎发生强制停止时,没有调用任何方法 - 包括 onDestroy()onStop()。如果是这种情况,那么为什么我的应用程序没有返回 newGame?在 Force Closing 时查看日志,一条消息说“onSavedInstance not called”,这是什么?

我觉得我应该完全避免 Serializable...

onCreate fragment

Game game;
 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    game =  LoadGame.Load(this); //LoadGame is the class which contains Save,Load methods

@Override
protected void onStop() {
    LoadGame.Save(this,game);
    super.onStop();
}

最佳答案

提示,序列化很棒,我一直在使用它,问题是,您实际上是在实际遇到问题的线程上进行保存,您是否期待对 onStop() 的神奇调用?所以要么

  • 您在不同的线程上定期调用您的保存方法,因此无论发生什么,它都会继续保存。-毕竟这是一个游戏-

  • 您可以在您的代码中添加一个 try/catch 并捕获某些异常并在不同的线程上手动调用一个保存方法,那么您需要病态的封装。这可能无法很好地为您服务,因为无法捕获诸如 noSuchMethod 等错误,因此可能会发生强制关闭

任您选择。

关于java - 将可序列化对象保存在持久存储中(android),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31215882/

相关文章:

java - java为什么不用@Serializable注解替换Serializable

java - 在我的 Kafka SpringBoot 应用程序的 @PostConstruct 方法中拆分数组时遇到问题

java - 打印 N 个数字之前的每个质数

android - 尝试通过 ListView 显示数据时应用程序崩溃

java - 如果我在 OnTouchListener 中返回 false,实际会发生什么?

php - android 中图像不显示

java - AudioSystem.getMixerInfo() 在 Java/gentoo 中什么也得不到

java - 输出 ArrayList 到 String 不出现 [,](括号)

C# DataContract 序列化,如何反序列化到已经存在的实例

python - 如何序列化 Keras 模型以与 Joblib 一起使用?