【问题标题】:Serializing an object that extends Application序列化扩展应用程序的对象
【发布时间】:2011-08-24 13:52:52
【问题描述】:

我正在开发一个必须跨活动维护全局状态的 android 项目。为此,我正在成功扩展应用程序。然而,该项目的一个新要求是即使应用程序被 android OS 杀死也要保持状态,对于这个简单的扩展应用程序是不够的,因为对象将与应用程序一起被杀死。

为了解决这个问题,我对扩展 Application 的对象实现了 Serializable:

    public class AppState extends Application implements Serializable

然后当主要活动被销毁时,我将对象写入私有存储:

    @Override
public void onDestroy() {
    super.onDestroy();
    ByteArrayOutputStream bos = null;
    ObjectOutputStream oos = null;
    FileOutputStream fos = null;
    // If there's a certificate creation in progress, let's store it more
    // permanently before killing the app.
    if (appState.getCertificate() != null) {
        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(appState);
            byte[] buf = bos.toByteArray();

            fos = openFileOutput(Constants.objectStoreFileName, Context.MODE_PRIVATE);
            fos.write(buf);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

然后我通过调用来恢复对象:

    private void getAppStateFromFile() {
    FileInputStream fis = null;
    ObjectInputStream ois = null;
    ByteArrayOutputStream bos = null;
    try {
        fis = openFileInput(Constants.objectStoreFileName);
        bos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = fis.read(b)) != -1) {
           bos.write(b, 0, bytesRead);
        }
        byte[] bytes = bos.toByteArray();
        ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        AppState appStateFromFile = (AppState) ois.readObject();
        if (appStateFromFile != null) {
            // restore values from appStateFromFile
        }
    } catch (StreamCorruptedException e) {
        e.printStackTrace();
    } catch (OptionalDataException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        deleteFile(Constants.objectStoreFileName);
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (ois != null) {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bos != null) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

效果很好,但我很好奇有多少人使用过这种方法。我认为这会很常见,因为我读过很多关于人们想要更永久地保存状态的信息。但令我惊讶的是,谷歌搜索“'extends Application implements Serializable' android”返回了 0 个结果。由于某种原因,这不是推荐的方法吗?否则,它可以作为其他面临相同问题的人的解决方案。

【问题讨论】:

  • 大声笑不要在应用程序上实现可序列化。而是创建一个 Singleton 对象,其中包含您想要的所有变量。然后,您可以使其可序列化并使用它。
  • 我很想知道它是否能正常工作,因为我已经在使用应用程序,所以很容易测试它。但后果会是什么?
  • 它确实有效。这就是为什么我问这是否出于某种原因是不好的做法。
  • 您没有显示您存储的变量,但我假设您将瞬态置于上下文等中,因此这意味着您还可以有一个单独的类来存储您的状态。这是不好的做法,因为它是代码膨胀/不必要的耦合/如果需要重构则无济于事/如果涉及到它则无法调试/丑陋!
  • 我在 AppState 类中只有私有成员和他们的 getter/setter。没有像onCreate() 或上下文这样的其他实现。不过,我不得不在一些不可序列化的对象上添加瞬态。

标签: android serialization


【解决方案1】:

SharedPreferences 使您能够以所需的方式保存状态,因此当Application 对象中发生更改时,全局变量会在SharedPreferences 中更新。 将 Application 用于全局状态很好,但我不确定在 Application 中调用 onDestroy 是最好的选择。 当在Application 中再次调用onCreate 时,您可以重新启动该状态。

【讨论】:

  • 哦,调用保存的是 ondestroy 活动。在这种情况下,我认为不一定会破坏 Application 对象,因此您可能会无缘无故地保存应用程序状态。我不确定,所以我可能会去检查自己,可以解释为什么其他人不以这种方式保存状态。
  • 这是一个非常好的主意,但在我的情况下它不太适用。我存储到文件的对象包含几个 ArrayList,将它们转换为 SharedPreferences 并返回将是太多的工作。
  • 是的,它是调用onDestroy() 的主要活动。也许我可以打电话给isFinishing() 来确定活动是正常完成还是被杀死。
猜你喜欢
  • 2012-05-13
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多