Как исправить исключение java.io.NotSerializableException: android.graphics.Bitmap - PullRequest
2 голосов
/ 21 января 2012

Здравствуйте, я пытаюсь сохранить местоположение изображения на экране во внутреннем хранилище, но я получаю NotSerializableException. Я отправился на поиски и обнаружил, что проблема заключается в том, что Bitmap не предназначен для сериализации по этой ссылке Проблема сериализации Drawable Я так и не понял, как он решил проблему, приведу пример.если бы кто-то мог объяснить, как он исправил свое NotSerializableException и помог мне получить мое, я был бы очень признателен


Вот мой класс Elememt

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

 }

Вот мой onTouchметод в моем классе Panel

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 ]

9 голосов
/ 05 мая 2012

Я просто столкнулся с той же проблемой. Как указал Питер, некоторые используемые вами классы не являются сериализуемыми.

Механизм Java по умолчанию попытается сериализовать ваш класс, который вы пометили как Serializable, и попытается сохранить все поля, не помеченные как transient. Если одно из этих полей, однако, имеет значение , а не Сериализуемое (например, 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);
        }
    }

}

Для Canvas и Matrix вам потребуется найти подходящие (сериализуемые) представления для их сохранения. Например, вы можете использовать метод Matrix.getValues() и Matrix.setValues(...) для перевода его в сериализуемый формат.

Надеюсь, это поможет вам. Вы также можете обратиться к следующим справочным материалам Oracle по поводу сериализации: Основы и Продвинутый

2 голосов
/ 21 января 2012

Ваша проблема не только Bitmap, но также Canvas и Matrix. Ни один из этих классов не является 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...