如何修复java.io.NotSerializableException:android.graphics.Bitmap

时间:2012-01-21 17:28:55

标签: android serializable

你好我试图将sreen上的图像位置保存到内部存储但是我得到一个NotSerializableException。我去搜索并发现问题是Bitmap不是为了在这个链接上序列化Problem serializing Drawable我从来没有真的明白他如何解决问题抛出这个例子。如果有人可以解释他如何修复他的NotSerializableException并帮助我与我相处,那将非常感激


这是我的Elememt Class

public class Element extends main implements Serializable{
private int mX;
private int mY;
int location2 ;
Matrix elementlocation;
private Bitmap mBitmap;
Canvas canvas2;

public Element(Resources res, int x, int y) {
  location2 =item3;
    mBitmap = BitmapFactory.decodeResource(res, location2);
    mX = x - mBitmap.getWidth() / 2;
    mY = y - mBitmap.getHeight() / 2;
  }

public Element(){

}
public void doDraw2(Canvas canvas) {
    elementlocation=new Matrix();
    elementlocation.postTranslate(mX,mY);
    canvas2=canvas;
    canvas2.drawBitmap(mBitmap, elementlocation,null);
    }
public void setelementlocation(float num1,float num2){
   elementlocation=new Matrix();
   elementlocation.postTranslate(num1,num2);
 }
 public Canvas getCanvas2(){
    return(canvas2);
 }
public String toString() {
    String sentence;
    sentence= mBitmap+" "+mX+" "+mY;
    return (sentence);
 }

 }

这是我的Panel类

中的onTouch方法
public boolean onTouchEvent(MotionEvent event) {
   mainactivity=new main();
    Log.v("test", "you have touched the sreen: ");      

 mElements.add(new Element(getResources(),(int) event.getX(),(int) event.get()));       
 mainactivity.writeElement(new Element(getResources(),(int) event.getX(),(int) event.getY()),this.getContext());
        Log.v("Gesture", "is 1 ");   
        return super.onTouchEvent(event);
}

这是我的主要课程中的写元素方法

  public void writeElement(Element obj, Context context){
    Log.v("main", "made it to method writeElement" );
    File f = new File(context.getFilesDir(),FILENAME);
    try {
fos = new FileOutputStream(f);
    ObjectOutputStream objectwrite = new ObjectOutputStream(fos);
    objectwrite.writeObject(obj);
 fos.close(); 
 Log.v("main", "file was  made File ");

 }catch (FileNotFoundException e){
    e.printStackTrace();
    Log.v("main", "file was not made File not found ");
 } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    Log.v("main", "file was not made File IOException ");
}
 }

更新

public Element(Resources res, int x, int y) {
    location2 =item3;
    ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
    mBitmap = BitmapFactory.decodeResource(res, location2);
    mX = x - mBitmap.getWidth() / 2;
    mY = y - mBitmap.getHeight() / 2;
    mBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 


}

2 个答案:

答案 0 :(得分:9)

我遇到了同样的问题。 正如彼得所指出的,你使用的几个类不是Serializable。

Java的默认机制将尝试序列化您标记为Serializable的类,并尝试保留未标记为transient的所有字段。 但是,如果其中一个字段 Serializable(例如android.graphics.Bitmap),那么对ObjectOutputStream.writeObject的调用将失败。

要解决此问题,您需要覆盖Java序列化Element类的方式。 对于我的CachedBitmap类,我使用了以下代码。

package XXX;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;

import org.apache.commons.io.output.ByteArrayOutputStream;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class CachedBitmap implements Serializable{

    private static final long serialVersionUID = -6298516694275121291L;

    Date inserted;
    transient Bitmap bitmap;
    String url;

    public CachedBitmap(){};

    public CachedBitmap(Bitmap b, Date insertionDate, String sourceUrl){
        bitmap = b;
        inserted = insertionDate;
        url = sourceUrl;
    }

    private void writeObject(ObjectOutputStream oos) throws IOException{
       // This will serialize all fields that you did not mark with 'transient'
       // (Java's default behaviour)
        oos.defaultWriteObject();
       // Now, manually serialize all transient fields that you want to be serialized
        if(bitmap!=null){
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            boolean success = bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream);
            if(success){
                oos.writeObject(byteStream.toByteArray());
            }
        }
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
       // Now, all again, deserializing - in the SAME ORDER!
       // All non-transient fields
        ois.defaultReadObject();
       // All other fields that you serialized
        byte[] image = (byte[]) ois.readObject();
        if(image != null && image.length > 0){
            bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
        }
    }

}

对于CanvasMatrix,您需要找到合适的(可序列化的)表示来存储它们。例如,您可以使用Matrix.getValues()Matrix.setValues(...)方法将其翻译成可序列化的格式。

希望这会对你有所帮助。您可能还想查阅Oracle关于序列化的以下参考资料:BasicsAdvanced

答案 1 :(得分:2)

您的问题不仅是Bitmap,还有CanvasMatrix。这些课程都不是Serializable

您不需要序列化整个Element对象,只需序列化相关数据,例如Matrix的参数,当然还有Bitmap

用于序列化位图:

bmp.compress(Bitmap.CompressFormat.PNG, 90, outputStream);

Matrix

// get matrix values
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);

// float[] to byte[]
ByteBuffer byteBuf = ByteBuffer.allocate(4 * array.length);
FloatBuffer floatBuf = byteBuf.asFloatBuffer();
floatBuf.put(array);
byte [] byte_array = byteBuf.array();

// write data
outputStream.write(byte_array);