如何跨Activity重启保留复杂对象?

时间:2009-10-28 11:16:06

标签: android serialization android-activity lifecycle

假设我有一个可序列化的Java Bean对象。当一个Activity故意通过onDestroy() 时(不被调用),我想安全地存储它。

我正在寻找一种不涉及创建数据库并将对象写入其中的方法(主要是因为a)Android的DB API非常糟糕b)因为数据库使应用程序更新成为一场噩梦,因为没有得体的支持用于应用迁移。)

我想过将对象序列化为ByteArrayOutputStream,base64编码并将其作为字符串写入SharedPreferences文件。或者那太远了?

更新

也许序列化到字符串的想法毕竟不是那么糟糕,似乎运作得很好。这就是我现在正在做的事情:

    public static String objectToString(Serializable object) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        new ObjectOutputStream(out).writeObject(object);
        byte[] data = out.toByteArray();
        out.close();

        out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out);
        b64.write(data);
        b64.close();
        out.close();

        return new String(out.toByteArray());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static Object stringToObject(String encodedObject) {
    try {
        return new ObjectInputStream(new Base64InputStream(
                new ByteArrayInputStream(encodedObject.getBytes()))).readObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

在onDestroy()中我可以简单地将Base64字符串写入首选项文件,在下一次活动启动期间我再次读取它之前它是安全的。它比我预期的要快得多,除非你的bean携带大量数据,否则效果非常好。更好的是,您不必维护数据库架构。

不过,我很好奇其他人是如何做到这一点的。

2 个答案:

答案 0 :(得分:9)

  

我正在寻找一种没有的方法   涉及创建数据库和编写   对象(主要是因为a)   Android的DB API太可怕了b)   因为数据库进行应用   更新噩梦,因为有   申请没有得体   迁移)。

Android的API实际上是相当合理的,主要是因为它是SQLite API的薄包装,而SQLite API对于嵌入式数据库来说是相当合理的。此外,Android确实通过SQLiteOpenHelper为应用升级提供架构升级方面的帮助。

  

它比我预期的要快得多   除非你的豆子含量很大   数据,它运作良好。

我听说有更多的开发人员从序列化中逃避,而不是听说过人们长期成功。就在过去的几天里,在SO #android上,我和一个人拼命地试图从他的应用程序中删除序列化。

  

更好的是,您不必维护数据库架构。

哦,是的,你这样做。当您更新应用程序并修改课程时,您认为会发生什么?执行bookkeeping以弄清楚如何从新版本的类反序列化该类的旧版本是一件苦差事,这是开发人员放弃序列化的原因之一。另外,不要忘记序列化不是事务性的,而SQLite是。

答案 1 :(得分:3)

我也在寻找一种很好的解/任何bean或活动状态的方法。我们都知道Activity的onStoreInstanceState()和onRestoreInstanceState()是多么痛苦。

我的活动只是将状态存储在onPause()中,并通过直接对象序列化在onCreate()生命周期钩子中恢复它们。

像你一样通过字符串进行序列化当然是可能的,但不太适合大数据并导致大量开销。此外,首选项实际上是存储首选项,而不是数据:)不幸的是,Parcelable / Parcel我们可以用于此目的,不建议存储到持久存储。

剩下的是一个简单的对象序列化 - 幸运的是android SDK具有ObjectInputStream和ObjectOutputStream类的实现,具有所有缺点和好处 - 就像我们在非Android Java世界中所做的那样,简单:

ObjectOutputStream.writeObject(yourPojo)

会为我们带来魔力,(记得实现Serializable标记接口)

此外,您可能希望查看以下上下文的API - ContextWrapper - Activity,它们对缓存本地数据(如图像)等非常有用:

.getCacheDir()
.getDir()
.openFileInput()
.openFileOutput()

快乐的黑客攻击:)