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

时间:2015-07-04 01:09:33

标签: java android serialization persistent-storage

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

我调用了使用加载和保存方法在活动之间传递对象。当应用程序关闭/销毁时,我还调用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对象会混乱。重新启动时,应用程序将加载已保存game的{​​{1}},但当用户通过应用程序更改/交互onStop()对象时,我的应用程序将关闭“意外停止“在手机屏幕上显示消息。通过查看日志,我知道在强制关闭/销毁后,game方法在启动时加载Game对象时,Load方法将返回game而不是newGame ,所以在某种程度上,Force Close之间的保存/加载过程会混淆一些东西。

在日志中,我看到了:

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?在强制关闭时查看日志,这条消息说“onSavedInstance没有被调用”,这是什么?

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

onCreate代码段

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();
}

1 个答案:

答案 0 :(得分:1)

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

  • 您可以在不同的线程上定期调用您的保存方法,因此无论发生什么事情,它都会一直保存.-在所有游戏之后 -

  • 您可以在代码中添加try / catch并捕获某些异常,并在不同的Thread上手动调用save方法,这样您需要生病的Encapsulation。这可能不适合您,因为noSuchMethod等错误无法捕获,因此可能会发生强制关闭

无论你喜欢哪种方式。