Some object don't save to Android internal memory

时光总嘲笑我的痴心妄想 提交于 2019-12-23 03:45:05

问题


I'm using the following code to save and retrieve objects to and from the Androids internal memory. I have tested it with a string object with success. When I try to save a Bitmap I get a IOException. (I found out that I have to call the compress method) So I notice that I can save some objects, what are the restrictions to saving objects?

When I save a object, does it only save the fields? Can I save objects that contains other objects? Please clear me up.

Code:

    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);

        }

    }

Thanks in advance.


回答1:


The restriction is that all objects have to be serializable (implement the interface Serializable). If an object data member of an object is not serializable, it has to be marked as transient:

private transient SomeClass notSerializable;

EDIT about serializing non-serializable members

It depends on what you are trying to serialize that is not serializable. Since this is a question tagged with Android it could be a Context object for example.

Contexts are not serializable for a good reason, they are tied to a life cycle, either of the application or of an Activity. Its state is volatile and even if you could serialize and deserialize it later, its internal state wouldn't make sense, since a new Context has been established, a new thread or even a different process may be running by now.

In case of data members like Contexts you need to declare them as transient and re-assign the fresh and valid current Context to the deserialized object.

If you are trying to serialize different kinds of objects that on the one hand just represent data like a bunch of strings and / or numbers, but on the other hand are not serializable, you have two options:

  • If these are your classes, then just add the Serializable interface to them
  • Or you could customize the serialization process in your class that has non-serializable data members

Customization can be done by implementing the methods

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

These methods are invoked on serialization / deserialization of the class. The trick is to take the data / state of a non-serializable object and pack that data into a serializable object instead. You could for example use any Collection object like an ArrayList for sequentially storing the raw data.

Let's assume you want to serialize a Location object (for geo location coordinates) and let's also assume that object is not serializable. But you know that it consists of three values which can be serialized:

  • double longitude
  • double latitude
  • double altitude
  • (and others like provider, speed, time...)

You could store these three values in an ArrayList or you could create your own custom, serializable class which stores these values for serialization purposes. Put the ArrayList or your serializable intermediate object into the ObjectOutputStream of your custom writeObject method.

In readObject you need to reverse these steps and reconstruct your data member that is not serializable based on the raw data you serialized.

I also suggest reading Sun's documentation about serialization




回答2:


Yes, you can save all types of data in an object, you just need to make sure that you are defining all the variables inside your object:

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

You also need to make sure that you are setting the fields off those objects using a set method:

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

}

}

If you don't explicitly set the fields, you won't be able to save them.




回答3:


From the Oracle's Javadoc:

An ObjectOutputStream writes both primitive data types and graphs of Java objects to an underlying OutputStream. The objects and other data can then be read (reconstituted) using an ObjectInputStream. Persistent storage of objects can be accomplished by using a file for the stream. If the stream is a network socket stream, the objects can be reconstituted on another host or in another process.

Only objects that support the java.io.Serializable or java.io.Externalizable interface can be serialized to an output streams. The class of each serializable object is encoded including the class name and signature of the class, the values of the object's non-static and non-transient fields and arrays, and including any other objects referenced by the object (except those that do not implement the java.io.Serializable interface themselves). Multiple references to the same object are encoded using a referece sharing mechanism, so that a graph of the object can be restored appropriately.

The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also.



来源:https://stackoverflow.com/questions/11416650/some-object-dont-save-to-android-internal-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!