10

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

我想保存这个类(它基本上形成了游戏的当前状态),以便玩家可以拿起并加载游戏。

我看到它的方式有两个选择:1)找到另一种保存游戏状态的方法。这里的任何帮助将不胜感激。

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

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

4

6 回答 6

15

用这样的类替换 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);
    }
}

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

祝你好运!

Barry PS 这段代码可以编译,但我没有用真正的位图测试过

于 2011-05-14T16:44:27.820 回答
2

我有同样的问题。

我决定这样。

BitmapParcelable,所以我在课堂上做了以下事情。

  1. 我制作了获取object 的Constructor和返回Bundle表示 Objects 数据的getter 。因此,虽然Bitmapparcelable,但Bundle可以将bitmap保存为parcelableBundle

  2. 当您需要在意图中传递 Date 时,您可以调用 objects getBundle()方法并传递 withIntent.putExtra(String key,Bundle value)

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

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

于 2015-02-26T10:49:38.137 回答
1

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

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

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其用于序列化目的。我还没有足够的分数来发表评论,所以我正在编辑自己的答案以发表此评论。

于 2011-07-10T09:05:48.480 回答
1

这是一个通用位图包装器:(从 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;
    }
}

如果要压缩位图并使串行对象更小,可以通过setCompressFormat和设置压缩setCompressQuality

例子:

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();
}
于 2018-10-04T10:45:30.093 回答
0

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

public final void writeByteArray (byte[] b)

public final void readByteArray (byte[] val)

您可能还想查看Parcel文档。

于 2011-05-14T15:37:17.643 回答
0

您可以使用以下 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/Serializable.html

于 2011-05-14T15:39:27.260 回答