Android 序列化问题

发布于 2024-11-07 02:03:12 字数 362 浏览 0 评论 0原文

我创建了一个类,它有几个成员变量,所有这些变量都是可序列化的......除了一个位图!我尝试扩展位图并实现可序列化,但不认为位图是最终类。

我想保存该类(它基本上构成了游戏的当前状态),以便玩家可以拾取并加载游戏。

在我看来,我有两个选择: 1)寻找另一种保存游戏状态的方法。任何帮助将不胜感激。

2) 将 bitmap 成员变量更改为 int,例如,创建一个 BitmapGetter 类,该类具有一个返回基于 int 的位图的静态方法。 (这个选项并不容易,因为我的类包含如此多的位图可能性,并且我创建游戏的方式意味着这将需要大量的努力。

基本上我没有人可以责怪,除了我自己,不加思考地懒惰地创建了一个位图变量,但我将不胜感激任何帮助...

I created a class, which has several member variables, all of which are serializable... except one Bitmap! I tried to extend bitmap and implement serializable, not thinking Bitmap is a final class.

I want to save the class (it basically forms the current state of a game) so a player can pick-up and load the game.

The way I see it I have two options:
1) Find another way to save the game state. Any help here would be appreciated.

2) change the bitmap member variable to an int, say, and create a BitmapGetter class that has a static method returning bitmaps based on ints. (This option is not easy, as my class contains so many bitmap possiblities and the way I created the game means this will require an incredible amount of effort.

Basically I have no one to blame but myself for lazily creating a bitmap variable without thinking, but I would appreciate any help...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

平生欢 2024-11-14 02:03:12

如何用这样的类替换 Bitmap:

public class SerialBitmap implements Serializable {

    public Bitmap bitmap;

    // TODO: Finish this constructor
    SerialBitmap(<some params>) {
        // Take your existing call to BitmapFactory and put it here
        bitmap = BitmapFactory.decodeSomething(<some params>);
    }

    // Converts the Bitmap into a byte array for serialization
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteStream);
        byte bitmapBytes[] = byteStream.toByteArray();
        out.write(bitmapBytes, 0, bitmapBytes.length);
    }

    // Deserializes a byte array representing the Bitmap and decodes it
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int b;
        while((b = in.read()) != -1)
            byteStream.write(b);
        byte bitmapBytes[] = byteStream.toByteArray();
        bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
    }
}

重写的 Serialized.writeObject() 和 readObject() 方法序列化字节而不是 Bitmap,因此该类是可序列化的。您将需要完成构造函数,因为我不知道您当前如何构造位图。最后要做的事情是将 YourClass.bitmap 的引用替换为 YourClass.serialBitmap.bitmap。

祝你好运!

巴里
PS 这段代码可以编译,但我还没有用真正的位图测试它

How about replacing Bitmap with a class like this:

public class SerialBitmap implements Serializable {

    public Bitmap bitmap;

    // TODO: Finish this constructor
    SerialBitmap(<some params>) {
        // Take your existing call to BitmapFactory and put it here
        bitmap = BitmapFactory.decodeSomething(<some params>);
    }

    // Converts the Bitmap into a byte array for serialization
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteStream);
        byte bitmapBytes[] = byteStream.toByteArray();
        out.write(bitmapBytes, 0, bitmapBytes.length);
    }

    // Deserializes a byte array representing the Bitmap and decodes it
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int b;
        while((b = in.read()) != -1)
            byteStream.write(b);
        byte bitmapBytes[] = byteStream.toByteArray();
        bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
    }
}

The overridden Serializable.writeObject() and readObject() methods serialize the bytes instead of the Bitmap so the class is serializable. You will need to finish the constructor because I don't know how you currently construct your Bitmap. The last thing to do is to replace references to YourClass.bitmap with YourClass.serialBitmap.bitmap.

Good luck!

Barry
P.S. This code compiles but I haven't tested it with a real bitmap

请别遗忘我 2024-11-14 02:03:12

我也遇到了同样的问题。

我就这样决定了。

BitmapParcelable,所以我对我的类进行了以下操作。

  1. 我创建了构造函数,它获取 Bundle 对象,以及 getter
    返回代表对象数据的Bundle。所以虽然位图
    parcelableBundle可以将位图保存为parcelable

  2. 当需要在intent中传递Date时,可以调用对象
    getBundle() 方法并通过 Intent.putExtra(String key,Bundle value)

    传递

  3. 在目标活动中,您将调用 getBundle(String key)代码>并传递它
    构造函数

    我认为这是非常简单的方法。

I had the same problem.

And i decided like this.

Bitmap is Parcelable, so I made following to my class.

  1. I made Constructor which gets Bundle object , and getter that
    returns Bundle representing Objects data. So while Bitmap is
    parcelable , Bundle can save bitmap as parcelable in it.

  2. When you need to pass Date in intent , you can call objects
    getBundle() method and pass with Intent.putExtra(String key,Bundle value)

  3. In target activity you will call getBundle(String key) and pass it
    to constructor.

    I think it's very easy approach.

始终不够 2024-11-14 02:03:12

这是一个通用的位图包装器:(从 Barry Fruitman 答案编辑)

    public class SerialBitmap implements Serializable {

    private Bitmap bitmap;
    private transient Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.PNG;
    private transient int compressQuality = 100;

    public SerialBitmap(Bitmap bitmap)
    {
        this.bitmap = bitmap;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void recycle() {
        if (bitmap!=null && !bitmap.isRecycled()) bitmap.recycle();
    }
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(compressFormat, compressQuality, stream);

        byte[] byteArray = stream.toByteArray();

        out.writeInt(byteArray.length);
        out.write(byteArray);

    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {


        int bufferLength = in.readInt();

        byte[] byteArray = new byte[bufferLength];

        int pos = 0;
        do {
            int read = in.read(byteArray, pos, bufferLength - pos);

            if (read != -1) {
                pos += read;
            } else {
                break;
            }

        } while (pos < bufferLength);

        bitmap = BitmapFactory.decodeByteArray(byteArray, 0, bufferLength);

    }

    public Bitmap.CompressFormat getCompressFormat() {
        return compressFormat;
    }

    public void setCompressFormat(Bitmap.CompressFormat compressFormat) {
        this.compressFormat = compressFormat;
    }

    public int getCompressQuality() {
        return compressQuality;
    }

    public void setCompressQuality(int compressQuality) {
        this.compressQuality = compressQuality;
    }
}

如果你想压缩位图并使串行对象更小
您可以通过 setCompressFormatsetCompressQuality 设置压缩。

示例:

setCompressFormat(Bitmap.CompressFormat.JPEG);
setCompressQuality(80);

如果您使用 Progourd,请添加以下规则:

-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

Here is a general bitmap wrapper: (Edit from Barry Fruitman answer)

    public class SerialBitmap implements Serializable {

    private Bitmap bitmap;
    private transient Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.PNG;
    private transient int compressQuality = 100;

    public SerialBitmap(Bitmap bitmap)
    {
        this.bitmap = bitmap;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void recycle() {
        if (bitmap!=null && !bitmap.isRecycled()) bitmap.recycle();
    }
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(compressFormat, compressQuality, stream);

        byte[] byteArray = stream.toByteArray();

        out.writeInt(byteArray.length);
        out.write(byteArray);

    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {


        int bufferLength = in.readInt();

        byte[] byteArray = new byte[bufferLength];

        int pos = 0;
        do {
            int read = in.read(byteArray, pos, bufferLength - pos);

            if (read != -1) {
                pos += read;
            } else {
                break;
            }

        } while (pos < bufferLength);

        bitmap = BitmapFactory.decodeByteArray(byteArray, 0, bufferLength);

    }

    public Bitmap.CompressFormat getCompressFormat() {
        return compressFormat;
    }

    public void setCompressFormat(Bitmap.CompressFormat compressFormat) {
        this.compressFormat = compressFormat;
    }

    public int getCompressQuality() {
        return compressQuality;
    }

    public void setCompressQuality(int compressQuality) {
        this.compressQuality = compressQuality;
    }
}

if you want to compress the bitmap and make the serial object smaller
you can set the compression via setCompressFormat and setCompressQuality.

Example:

setCompressFormat(Bitmap.CompressFormat.JPEG);
setCompressQuality(80);

If you are using Progourd, add the following rules:

-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
世界等同你 2024-11-14 02:03:12

如果可以在应用程序中单独保存位图数据,则可以执行以下操作:

在保存当前状态的类中,将位图保存到您选择的文件夹中:

FileOutputStream out = new FileOutputStream(<path to bmp>);
bitmap.compress(CompressFormat.PNG, 100, out);

在将位图作为成员的类中,将将路径作为可序列化成员并在反序列化后重建位图:

public class MyClass implements Serializable
{
    // ...
    private String bitmapPath;
    transient Bitmap bitmap;
    // ...

    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
    {
        in.defaultReadObject();
        bitmap = BitmapFactory.decodeFile(path);
    }

如果需要,您可以在 readObject() 函数中实现任何其他构建功能,因为对象是在 defaultReadObject 之后完全构造的() 调用。

希望这有帮助。

顺便说一句,http://developer.android.com/reference/android/os/Parcel .html 建议不要使用 Parcelable 进行序列化。我还没有足够的积分来发表评论,因此我正在编辑自己的答案以添加此评论。

If it is OK to save the bitmap data separately in your application, you can do the following:

In your class that saves the current state, save the bitmap to a folder of your choice:

FileOutputStream out = new FileOutputStream(<path to bmp>);
bitmap.compress(CompressFormat.PNG, 100, out);

In the class that has the bitmap as member, have the path as the serializable member and reconstruct the bitmap after deserialization:

public class MyClass implements Serializable
{
    // ...
    private String bitmapPath;
    transient Bitmap bitmap;
    // ...

    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
    {
        in.defaultReadObject();
        bitmap = BitmapFactory.decodeFile(path);
    }

You can implement any other build-up functionality in the readObject() function if needed, since the object is fully constructed after the defaultReadObject() call.

Hope this helps.

BTW, http://developer.android.com/reference/android/os/Parcel.html recommends against using Parcelable for serialization purposes. I do not have enough points yet to leave a comment, so I am editing my own answer to put in this remark.

拥抱影子 2024-11-14 02:03:12

首先,您应该通过 Parcelable 进行序列化。它是一个 Android 类,通常开箱即用,效果很好:您可以使用它序列化 ByteArray,方法如下:

public final void writeByteArray (byte[] b)

您可能

public final void readByteArray (byte[] val)

需要检查 Parcel 文档。

First of all, you should serialize via Parcelable. It's an Android class and it usually works great, out of the box: and you can serialize a ByteArray with it, with the methods:

public final void writeByteArray (byte[] b)

and

public final void readByteArray (byte[] val)

You might want to check Parcel documentation too.

忘你却要生生世世 2024-11-14 02:03:12

您可以使用以下 java 方法手动执行序列化:

private void writeObject(java.io.ObjectOutputStream out)
private void readObject(java.io.ObjectInputStream in)

使用 getPixels 序列化位图,并且在执行反序列化时,可以使用 createBitmap 从头开始​​重新创建它。

您可以在此处阅读有关如何使用 readObject 和 writeObject 的信息: http://download.oracle.com/javase/6/docs/api/java/io/Serializing.html

You can do the serialization by hand by using the following java methods:

private void writeObject(java.io.ObjectOutputStream out)
private void readObject(java.io.ObjectInputStream in)

Serialize the bitmap by using getPixels and when you do the deserialization you can use createBitmap to recreate it from scratch.

You can read about on how to use readObject and writeObject here: http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文