22

假设我有一个可序列化的 Java Bean 对象。当 Activity 故意通过 onDestroy()(即调用 onSaveInstanceState()),我想将其安全地存储起来。

我正在寻找一种不涉及创建数据库并将对象写入该数据库的方法(主要是因为 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 携带大量数据,否则它工作得很好。更好的是,您不必维护数据库模式。

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

4

2 回答 2

9

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

Android 的 API 实际上是相当合理的,主要是因为它是对 SQLite API 的薄包装,而 SQLite API 对于嵌入式数据库来说是相当合理的。此外,Android 确实通过SQLiteOpenHelper.

它比我预期的要快得多,除非你的 bean 携带大量数据,否则它工作得很好。

我听说过很多开发人员因序列化而尖叫着逃跑,而不是听说过有人在序列化方面取得了长期成功。就在过去的几天里,在 SO #android 上,我与一个拼命试图从他的应用程序中彻底删除序列化的人进行了交流。

更好的是,您不必维护数据库模式。

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

于 2009-10-28T14:09:04.717 回答
3

I was also looking for a nice approach of un/marshalling any beans or activity states. We all know how much Activity's onStoreInstanceState() and onRestoreInstanceState() is a pain.

My acitivities simply store their states in onPause() and restore them in onCreate() lifecycle hooks via direct object serialization.

Serialization via a String like you do, is of course possible but less suitable for big data and causes a lot of overhead. Moreover Preferences are actually there to store preferences, not data :) Unfortunately, the Parcelable / Parcel what we could use for this purpose, does not recommend to store to persistent storage.

So what's left over is a simple object serialization - fortunately android SDK has implementation of the ObjectInputStream and ObjectOutputStream classes with all drawbacks and benefits - like we would also do in a non-android Java world, a simple:

ObjectOutputStream.writeObject(yourPojo)

would do the magic for us, (remember to implement the Serializable marker-interface)

Also, you may want to look in following APIs of a Context - ContextWrapper - Activity, which are very useful to cache local data (such as images) etc:

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

happy hacking :)

于 2013-02-16T14:56:04.850 回答