我创建了一个类,它有几个成员变量,所有这些都是可序列化的......除了一个Bitmap!我试图扩展位图并实现可序列化,而不是认为Bitmap是最后一类。
我想保存课程(它基本上形成了游戏的当前状态),因此玩家可以提升并加载游戏。
我看到它的方式我有两个选择: 1)找到另一种保存游戏状态的方法。这里的任何帮助将不胜感激。
2)将位图成员变量更改为int,比如说,并创建一个BitmapGetter类,该类具有基于int返回位图的静态方法。 (这个选项并不容易,因为我的类包含了很多位图可能性,而且我创建游戏的方式意味着需要花费大量精力。
基本上我没有人责怪,但我自己懒得创建一个位图变量而不考虑,但我会感激任何帮助......
答案 0 :(得分:14)
如何用这样的类替换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()方法序列化字节而不是Bitmap,因此该类是可序列化的。您将需要完成构造函数,因为我不知道您当前如何构造您的Bitmap。最后要做的是用YourClass.serialBitmap.bitmap替换对YourClass.bitmap的引用。
祝你好运!巴里 附:这段代码编译但我还没有用真正的位图测试它
答案 1 :(得分:2)
我遇到了同样的问题。
我决定这样。
Bitmap
是Parcelable
,所以我跟随我的班级。
我创建了构造函数,它获取了Bundle
个对象, getter
返回表示对象数据的 Bundle 。所以,虽然 Bitmap 是
parcelable , Bundle 可以将位图保存为 parcelable 。
当您需要在意图中传递日期时,您可以调用对象
getBundle()
方法并通过Intent.putExtra(String key,Bundle value)
在目标活动中,您将调用getBundle(String key)
并将其传递
到构造函数。
我认为这很简单。
答案 2 :(得分: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();
}
答案 3 :(得分:0)
首先,您应该通过Parcelable序列化。它是一个Android类,它通常很好用,开箱即用:你可以使用方法序列化ByteArray:
public final void writeByteArray (byte[] b)
和
public final void readByteArray (byte[] val)
您可能也想查看Parcel文档。
答案 4 :(得分: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
答案 5 :(得分:0)
如果可以在应用程序中单独保存位图数据,则可以执行以下操作:
在保存当前状态的类中,将位图保存到您选择的文件夹中:
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()
调用后完全构造的。
希望这有帮助。
BTW,http://developer.android.com/reference/android/os/Parcel.html建议不要使用Parcelable
进行序列化。我还没有足够的意见留下评论,所以我正在编辑我自己的答案以加入这句话。