Android:在不使用 marshall() 的情况下从 Parcelable 到 Serializable 的任何快捷方式?

Posted

技术标签:

【中文标题】Android:在不使用 marshall() 的情况下从 Parcelable 到 Serializable 的任何快捷方式?【英文标题】:Android: Any shortcut to Serializable from Parcelable without using marshall()? 【发布时间】:2011-08-19 07:06:13 【问题描述】:

我知道Parcelable(快)和Serializable(慢)之间的性能差异。但是,我需要持久存储某些应用程序信息,而不仅仅是在一个生命周期内,因此使用 Parcelable 对象的 onSaveInstanceState 和关联方法是不合适的。

所以我把注意力转向Serializable。主要是我有AbstractList 类型要存储——这很好,因为它们实现了Serializable。但是,我存储在其中的许多类型是 Parcelable 而不是 Serializable,例如RectF.

我认为“没问题”,因为我可以通过Parcelable.writeToParcel(parcel, flags) 轻松生成一个包裹,然后在其上调用marshall() 来创建一个byte[],我可以对其进行序列化和反序列化。我想我会使用泛型;创建一个SerializableParcelable<Parcelable> implements Serializable 类,为我希望序列化的所有Parcelable 类型提供一个适合的解决方案。然后我会例如将每个 RectF 存储在 ArrayList 中的此包装器中,并且您瞧,该列表及其 Parcelable 内容是可序列化的。

但是,API 文档声明 marshall() 不得用于持久存储:

公共最终字节[] marshall ()

返回包裹的原始字节数。

您在此处检索的数据不得放置在任何类型的持久性存储中(本地磁盘、网络等)。为此,您应该使用标准序列化或另一种通用序列化机制。 Parcel marshalled 表示针对本地 IPC 进行了高度优化,因此不会尝试保持与平台不同版本中创建的数据的兼容性。

所以现在我被困住了。我可以忽略此警告并遵循我上面概述的路线,或者通过扩展每个我想要序列化的 Parcelable 来规避问题并创建定制的序列化方法,这似乎非常浪费时间和精力。

有谁知道在不使用marshall() 的情况下序列化Parcelable 对象的“正确”快捷方式?或者我应该在不注意指定警告的情况下继续耕种?也许 SQLite 数据库是要走的路,但我不确定,希望得到您的建议。

非常感谢。

【问题讨论】:

有什么原因不能使用SharedPreferences 来存储持久数据吗?哦,等等,答案很明显,对不起! SharedPreferences 仅提供持久存储简单类型(如 int、String 等)的方法。没有存储 Parcelable、Serializable 或 byte[] 的功能。 是的,我刚刚意识到这一点。 /o\ 【参考方案1】:

对于任何需要序列化的对象,您可以使用objectOutPutStream。通过使用它,您可以将对象写入设备的文件系统。所以这也可以用来保存Parcelable对象。

以下是将对象保存到文件系统的代码。

    public static void witeObjectToFile(Context context, Object object, String        filename) 

    ObjectOutputStream objectOut = null;
    FileOutputStream fileOut = null;
    try 
        File file = new File(filename);
        if(!file.exists())
            file.createNewFile();
        
        fileOut = new FileOutputStream(file,false);
        objectOut = new ObjectOutputStream(fileOut);
        objectOut.writeObject(object);
        fileOut.getFD().sync();

     catch (IOException e) 
        e.printStackTrace();
     catch (NullPointerException e) 
        e.printStackTrace();
    finally 
        if (objectOut != null) 
            try 
                objectOut.close();
             catch (IOException e) 
                // do nowt
            
        
        if (fileOut != null) 
            try 
                fileOut.close();
             catch (IOException e) 
                // do nowt
            
        
    
`

为了读取对象使用 ObjectInputStream 。找到下面的代码。

    public static Object readObjectFromFile(Context context, String filename) 

    ObjectInputStream objectIn = null;
    Object object = null;
    FileInputStream fileIn = null;
    try 
        File file = new File(filename);
        fileIn = new FileInputStream(file);//context.getApplicationContext().openFileInput(filename);
        objectIn = new ObjectInputStream(fileIn);
        object = objectIn.readObject();

     catch (FileNotFoundException e) 
        // Do nothing
    catch (NullPointerException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     catch (Exception e) 
        // TODO: handle exception
        e.printStackTrace();
    finally 
        if (objectIn != null) 
            try 
                objectIn.close();
             catch (IOException e) 
                // do nowt
            
        
        if(fileIn != null)
            try 
                fileIn.close();
             catch (IOException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        
    

    return object;
`

问候, 沙

【讨论】:

你错过了 ObjectOutputStream.writeObject(object) 如果对象未声明为 Serilizable 将引发非 Serializable 错误这一点。这是@KomodoDaveis 描述的问题的全部根源。 Parcelables 不一定是可序列化的。我也在努力解决同样的问题,试图持久化具有 Bundles 的 Intent 对象。

以上是关于Android:在不使用 marshall() 的情况下从 Parcelable 到 Serializable 的任何快捷方式?的主要内容,如果未能解决你的问题,请参考以下文章

sql [存档Marshall中的陈旧瞬态]从Marshall Inbox归档旧对象#marshall

如何使用 Spring Ws marshall 调用 Paypal ws?

在 c# 中使用 ifdef 和联合的 Marshall 结构

使用JAXB在XML元素中使用marshall属性

Marshall @Id 到 JSON,同时保留 Java 8 时间格式

C# - Marshall by value 问题!