1

我正在使用以下代码在 Android 内部存储器中保存和检索对象。我已经成功地使用字符串对象对其进行了测试。当我尝试保存位图时,我得到一个 IOException。(我发现我必须调用compress方法)所以我注意到我可以保存一些对象,保存对象有什么限制?

当我保存一个对象时,它是否只保存字段?我可以保存包含其他对象的对象吗?请把我清理干净。

代码:

    public Object readObjectFromMemory(String filename) {
        Object defautObject = null;
        FileInputStream fis;
        try {
            fis = game.openFileInput(filename);
            ObjectInputStream is = new ObjectInputStream(fis);
            defautObject = is.readObject();
            is.close();
            this.gameEngineLog.d(classTAG, "Object successfully read: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "FileNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (StreamCorruptedException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "StreamCorruptedException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "IOException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (ClassNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "ClassNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        }

        return defautObject;

    }

public void writeObjectToMemory(String filename, Object object) {
        FileOutputStream fos;
        try {
            fos = game.openFileOutput(filename, Context.MODE_PRIVATE);
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(object);
            os.close();
            this.gameEngineLog.d(classTAG, "Object successfully written: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        }

    }

提前致谢。

4

3 回答 3

1

限制是所有对象都必须是可序列化的(实现接口 Serializable)。如果对象的对象数据成员不可序列化,则必须将其标记为瞬态:

private transient SomeClass notSerializable;

关于序列化不可序列化成员的编辑

这取决于您尝试序列化的不可序列化的内容。由于这是一个用 Android 标记的问题,因此它可能是一个 Context 对象。

上下文不可序列化是有充分理由的,它们与应用程序或活动的生命周期相关联。它的状态是不稳定的,即使你以后可以序列化和反序列化它,它的内部状态也没有意义,因为已经建立了一个新的上下文,一个新的线程甚至不同的进程现在可能正在运行。

对于像 Contexts 这样的数据成员,您需要将它们声明为瞬态并将新鲜且有效的当前 Context 重新分配给反序列化对象。

如果您尝试序列化不同类型的对象,这些对象一方面仅表示数据,如一堆字符串和/或数字,但另一方面不可序列化,您有两种选择:

  • 如果这些是您的类,那么只需向它们添加 Serializable 接口
  • 或者您可以在具有不可序列化数据成员的类中自定义序列化过程

自定义可以通过实现方法来完成

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

这些方法在类的序列化/反序列化时调用。诀窍是获取不可序列化对象的数据/状态并将该数据打包到可序列化对象中。例如,您可以使用任何 Collection 对象(如 ArrayList)来顺序存储原始数据。

假设您要序列化 ​​Location 对象(用于地理位置坐标),并且还假设该对象不可序列化。但是您知道它由三个可以序列化的值组成:

  • 双经度
  • 双纬度
  • 双高度
  • (以及其他人,如提供者、速度、时间......)

您可以将这三个值存储在 ArrayList 中,或者您可以创建自己的自定义、可序列化的类来存储这些值以用于序列化目的。将 ArrayList 或可序列化的中间对象放入自定义 writeObject 方法的 ObjectOutputStream 中。

在 readObject 中,您需要反转这些步骤并根据您序列化的原始数据重建不可序列化的数据成员。

我还建议阅读 Sun关于序列化的文档

于 2012-07-10T15:27:21.890 回答
0

是的,您可以将所有类型的数据保存在一个对象中,您只需要确保您在对象中定义了所有变量:

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
}

您还需要确保使用 set 方法设置这些对象的字段:

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
//sets the value of yourInt
public void setYourInteger(int yourInt){
 this.yourInt = yourInt;

}

}

如果您没有明确设置字段,您将无法保存它们。

于 2012-07-10T15:29:53.037 回答
0

来自 Oracle 的 Javadoc:

ObjectOutputStream 将 Java 对象的原始数据类型和图形写入底层 OutputStream。然后可以使用 ObjectInputStream 读取(重构)对象和其他数据。对象的持久存储可以通过使用流的文件来实现。如果流是网络套接字流,则可以在另一个主机或另一个进程中重构对象。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能序列化为输出流。每个可序列化对象的类都被编码,包括类的类名和签名,对象的非静态和非瞬态字段和数组的值,包括对象引用的任何其他对象(除了那些没有实现java.io.Serializable 接口本身)。对同一对象的多个引用使用引用共享机制进行编码,以便可以适当地恢复对象的图形。

对象的默认序列化机制写入对象的类、类签名以及所有非瞬态和非静态字段的值。对其他对象的引用(瞬态或静态字段除外)也会导致这些对象被写入。

于 2012-07-10T15:30:53.643 回答