【问题标题】:Android Problem Saving Serializable object with array attributesAndroid问题保存具有数组属性的可序列化对象
【发布时间】:2011-11-10 04:33:45
【问题描述】:

大家好,我正在实现序列化并将对象保存在 android 设备内存中。我有一个用来保存和获取对象的类。问题是我要保存的类的属性是我在我的应用程序中拥有的其他对象的数组列表,当我尝试保存它时,我从应用程序中得到一个未知数。

两个类的代码下面:

public class CacheTest {

private static final long serialVersionUID = 1L;
public boolean classEnabled;
private File cacheDir;

public CacheTest(Context context) {
    // Find the dir to save cached images
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
        cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "lacartelera");
    else
        cacheDir = context.getCacheDir();
    if (!cacheDir.exists())
        cacheDir.mkdirs();
}

public boolean saveObject(StreamData obj) {

    final File suspend_f = new File(cacheDir, "streamdata");

    FileOutputStream fos = null;
    ObjectOutputStream oos = null;
    boolean keep = true;

    try {
        fos = new FileOutputStream(suspend_f);
        oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);
    } catch (Exception e) {
        keep = false;

    } finally {
        try {
            if (oos != null)
                oos.close();
            if (fos != null)
                fos.close();
            if (keep == false)
                suspend_f.delete();
        } catch (Exception e) {         
        }
    }
    return keep;
}

public void clear() {
    File[] files = cacheDir.listFiles();
    for (File f : files)
        f.delete();
}

public StreamData getObject() {
    final File suspend_f = new File(cacheDir, "streamdata");

    StreamData streamData = null;
    FileInputStream fis = null;
    ObjectInputStream is = null;
    String val = "";
    // boolean keep = true;
    try {

        fis = new FileInputStream(suspend_f);
        is = new ObjectInputStream(fis);
        streamData = (StreamData) is.readObject();
    } catch (Exception e) {
        val = e.getMessage();

    } finally {
        try {
            if (fis != null)
                fis.close();
            if (is != null)
                is.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    return streamData;

}
}


public class StreamData implements Serializable {
/**
 * 
 */
private static final long serialVersionUID = 1L;
private int _idStream = 0;
private int _idMensaje = 0;
private String _titulo = "";
private String _mensaje = "";
private String _fechaInicio = "";
private String _fechaFin = "";
private boolean _smartFilter = true;
private boolean _hasChanges = false;

private boolean _notifyUpdates = true;

public ArrayList<Cine> _cines = new ArrayList<Cine>();
public ArrayList<Pelicula> _peliculas = new ArrayList<Pelicula>();
public ArrayList<Pelicula> _estrenos = new ArrayList<Pelicula>();
public ArrayList<Pelicula> _proximamente = new ArrayList<Pelicula>();

public int getIdStream() {
    return _idStream;
}

public void setIdStream(int value) {
    _idStream = value;
}

public int getIdMensaje() {
    return _idMensaje;
}


}

更新:我在 logcat 调试器中看到:

09-04 14:57:16.353: ERROR/AndroidRuntime(959): at dalvik.system.BlockGuard.getThreadPolicy(BlockGuard.java:133) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at dalvik.system.BlockGuard$WrappedFileSystem.write(BlockGuard.java:170) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.FileOutputStream.write(FileOutputStream.java:318) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.DataOutputStream.writeByte(DataOutputStream.java:145) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1539) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.util.ArrayList.writeObject(ArrayList.java:651) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.lang.reflect.Method.invokeNative(Native Method) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.lang.reflect.Method.invoke(Method.java:507) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.util.ArrayList.writeObject(ArrayList.java:651) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.lang.reflect.Method.invokeNative(Native Method) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.lang.reflect.Method.invoke(Method.java:507) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689) 09-04 14:57:16.353: ERROR/AndroidRuntime(959): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653) 0

其他类的代码

公共类 Cine 实现 Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public Cine() {
}

public Cine(int idCine) {
    _idCine = idCine;
}

public String toString() {
    return _cine;
}


public void setDelete(boolean value) {
    _delete = value;

    if (value)
        _programacionesPeliculas.clear();
}

private ArrayList<ProgramacionPelicula> _programacionesPeliculas = new ArrayList<ProgramacionPelicula>();

public ArrayList<ProgramacionPelicula> getProgramacionesPeliculas() {
    return _programacionesPeliculas;
}

public void addProgramacionPelicula(ProgramacionPelicula programacion) {
    _programacionesPeliculas.add(programacion);
}

}

公共类 Pelicula 实现 Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public Pelicula() 
{
}



private int _listIndex = 0;

public void setListIndex(int value) {
    _listIndex = value;
}

public int getListIndex() {
    return _listIndex;
}

private ArrayList<ProgramacionPelicula> _presentandoceEn = new ArrayList<ProgramacionPelicula>();

public void addPresentandoceEn(ProgramacionPelicula programacion) {
    _presentandoceEn.add(programacion);
}

public ArrayList<ProgramacionPelicula> getPresentandoceEn() {
    return _presentandoceEn;
}

public void setPresentandose(Object[] programaciones) {
    for (Object programacion : programaciones) {
        if (programacion instanceof ProgramacionPelicula)
            _presentandoceEn.add((ProgramacionPelicula) programacion);
    }
}

}

公共类 ProgramacionPelicula 实现 Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;

public ProgramacionPelicula() {
}

public ProgramacionPelicula(Pelicula pelicula) {
    _pelicula = pelicula;
}

public ProgramacionPelicula(Cine cine) {
    _cine = cine;
}

public String toString() {
    if (getVista() == ProgramacionPelicula.VISTA_PELICULA)
        return getCine().getCine();
    else
        return getPelicula().getTituloOriginal();
}

private int _idProgramacion;

public void setIdProgramacion(int value) {
    _idProgramacion = value;
}

public int getIdProgramacion() {
    return _idProgramacion;
}

private Pelicula _pelicula;

public void setPelicula(Pelicula pelicula) {
    _pelicula = pelicula;
}

public Pelicula getPelicula() {
    return _pelicula;
}

private Cine _cine;

public void setCine(Cine cine) {
    _cine = cine;
}

public Cine getCine() {
    return _cine;
}

public ArrayList<Tanda> _tandas = new ArrayList<Tanda>();

public void setTandas(ArrayList<Tanda> value) {
    _tandas = value;
}

public void setTandas(Object[] tandas) {
    for (Object tanda : tandas) {
        if (tanda instanceof Tanda)
            _tandas.add((Tanda) tanda);
    }
}

public void addTanda(Tanda value) {
    _tandas.add(value);
}

public ArrayList<Tanda> getTandas() {
    return _tandas;
}

public String getListTandas() {
    StringBuilder result = new StringBuilder();
    for (Tanda tanda : getTandas()) {

        result.append("  " + tanda.getDiaSemana());
        result.append("  " + tanda.getDescripcion());
        result.append("  " + tanda.getPrecio());
        result.append("<br/>");

    }

    return result.toString();
}

private String _sala = "";

public void setSala(String value) {
    _sala = value;
}

public String getSala() {
    return _sala;
}

public static final int VISTA_CINE = 0;
public static final int VISTA_PELICULA = 1;

private int _vista = VISTA_CINE;

public int getVista() {
    return _vista;
}

public ProgramacionPelicula toPelicula() {
    ProgramacionPelicula programacionPelicula = new ProgramacionPelicula();
    programacionPelicula._idProgramacion = _idProgramacion;
    programacionPelicula._pelicula = _pelicula;
    programacionPelicula._cine = _cine;
    programacionPelicula._tandas = _tandas;
    programacionPelicula._sala = _sala;
    programacionPelicula._vista = VISTA_PELICULA;

    return programacionPelicula;
}

}

提前致谢。

【问题讨论】:

  • 您遇到的确切异常和堆栈跟踪或任何错误是什么?
  • 请减少并正确格式化您的代码,这个问题太长了,无法吸引感兴趣的回答者。要格式化长代码块,请选择它并单击编辑器工具栏中的{ }。此外,所有这些 setter/getter 都不是必需的——他们在那里的评论就可以了。
  • 好的,谢谢你的信息。

标签: android serialization


【解决方案1】:

根据 cmets 和堆栈,您在编写对象时似乎有导致 StackOverFlow 的循环引用。确保您的对象 Pelicula、Cine、StreamData 及其实例变量没有相互引用。

您需要剪切引用并确保没有循环引用。在您的情况下,很可能是:

Pelicula 和 Cine 都包含:

ArrayList _presentandoceEn

作为它的实例变量并遵循 ProgramacionPelicula 包含这两个变量:

私人 Pelicula _pelicula; 私人电影_cine;

这可能会引用您尝试在 StreamData 中序列化的相同原始 Pelicula 或 Cine 对象,从而导致无限继续,直到它抛出 StackOverlow

您需要考虑重组类以避免此类问题。从我所看到的(我可能错了),我认为您正在考虑存储电影/电视节目。在这种情况下,由于 ProgramacionPelicula 包含详细信息,您可能希望将其存储在 StreamData 中,并从 Cine 和 Pelicula 中删除 ProgramacionPelicula 的引用。从逻辑上讲,程序应该包含包括 Cine 和 Pelicula 对象在内的详细信息,但 Cine/Pelicula 不应该包含程序列表(尤其是引用自身的程序)。这是需要考虑的事情。

【讨论】:

  • 我有所有这些对象的 StreamData 数组
  • 你需要剪切引用,确保你引用的不是同一个对象。让我更新我的答案以明确
  • 问题是我需要 Cine 和 Pelicula 对象有一个 ProgramacionPelicula 列表,它是相关信息的详细信息。
  • 我已将我的建议添加到答案中。这是需要考虑的事情。看起来您的问题与循环参考有关,我会首先通过切断参考来确认这一点,看看是否有效。如果你已经确认它确实是一个循环引用,那么你需要开始考虑重构你的代码以避免循环引用
  • 我认为你是对的,我会修改代码并让你知道。谢谢
【解决方案2】:

当您序列化一个对象时,Java 将遍历整个对象图。您的CinePelicula 类是否也实现了Serializable 接口?

【讨论】:

    【解决方案3】:

    Serializable 是一个标记接口,但您可以实现自己的序列化规则和处理 只需覆盖:

     private void writeObject(java.io.ObjectOutputStream out)
         throws IOException
     private void readObject(java.io.ObjectInputStream in)
         throws IOException, ClassNotFoundException;
     private void readObjectNoData() 
         throws ObjectStreamException;
    

    更多http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 2016-01-05
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多