【问题标题】:Persisting an ArrayList - cannot convert from Object to ArrayList持久化 ArrayList - 无法从 Object 转换为 ArrayList
【发布时间】:2013-08-12 16:21:04
【问题描述】:

把我的头撞在墙上。我正在从 Blackberry 转换为 Android。

我有一个需要保留日志的应用。这是一个简单的 ArrayList,不会那么大。它确实需要在应用程序重新启动等之间持续存在。但它还不够复杂,无法使用 SQL。它需要显示在 ListView 中,因此 ArrayList 似乎最简单。

我似乎能够轻松地序列化和存储 ArrayList。但是在重新读回它时,它会说我不能从 Object 转换为 ArrayList。

我的计划是让日志对象(单例)在我获取实例时加载历史记录。然后我会用 onDestroy() 将它写入一个文件...

在黑莓上,这种事情很容易。我很惊讶你需要在 Android 上做多少工作。 Android上的其他一切似乎都更容易。我更喜欢将对象标记为持久并让系统为我管理它的方法。我知道你也不能轻易地将 Object 填充到 SharedPreference 中。

有人可以指出我哪里出错了吗?我已经重新连接了几种方法,但问题仍然存在。如果有更简单的方法,请告诉。

谢谢

我有:

public class DataLog implements Serializable {
    private static final long serialVersionUID = 0L;
    private static String fileName = "datalog.dat";

    private static ArrayList<String> log = null;

    static public ArrayList<String> getInstance() {
        if (log == null) {
            synchronized (DataLog.class) {
                if (log == null) {
                    log = new ArrayList<String>();
                }
            }
            load();
        }
        return log;
    }

    public DataLog() {
        super();
    }

    public boolean add(String entry) {
        return log.add(entry);
    }

    public void add(int index, String entry) {
        if (index > 0)
            log.add(index, entry);
        else
            log.add(entry);
        save();
    }

    public void clear() {
        log.clear();
    }
    public void save() {
        Persister.store(fileName, log);
    }

    public static void load() {
        log = (ArrayList<String>) Persister.restore(fileName);
    }
}

public class Persister {
    static Context context = ThisApplication.context;

    public Persister() {}

    public static boolean store(String fileName, Object obj){
        File file = context.getFileStreamPath(fileName);

        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(obj);
            oos.close();
            fos.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return true;

    }
    public static Object restore(String fileName){
        File file = context.getFileStreamPath(fileName);
        Object obj = new Object();

        if(file.exists() && file.length()>0){
            FileInputStream fis = null;
            ObjectInputStream ois = null;
            try {
                fis = new FileInputStream(file);
                ois = new ObjectInputStream(fis);
                obj = ois.readObject();
                ois.close();
                fis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
        }
        return obj;
    }
}

【问题讨论】:

    标签: android serialization android-listview arraylist


    【解决方案1】:

    如果文件不存在,那么Persister.restore 实际上会返回一个new Object(),它不是ArrayList 的一个实例。你可以这样做:

    public static ArrayList<String> restore(String fileName){
        File file = context.getFileStreamPath(fileName);
        ArrayList<String> obj = null; // returning null indicates error
    
        if(file.exists() && file.length()>0){
            FileInputStream fis = null;
            ObjectInputStream ois = null;
            try {
                fis = new FileInputStream(file);
                ois = new ObjectInputStream(fis);
                obj = (ArrayList<String>) ois.readObject();
                ois.close();
                fis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
        } else {
            obj = new ArrayList<String>();
        }
        return obj;
    }
    

    然后您可以从load() 中删除演员表(因为它现在在Persister.restore 中):

    public static void load() {
        log = Persister.restore(fileName);
    }
    

    我还将更改Persister.store() 以接受明确的ArrayList&lt;String&gt; 参数而不是一般的Object

    public static boolean store(String fileName, ArrayList<String> obj){
        // method body does not need to change
    }
    

    这样,编译器将捕获您尝试保留 ArrayList&lt;String&gt; 以外的任何内容的任何编程错误。

    【讨论】:

    • 这部分现在可以工作了。谢谢。但是我现在陷入了按值传递的地狱……我的 Java 教育中肯定存在一些漏洞。
    • UI 有一个 ListView 和一个 ArrayAdapter 引用原始对象。当我恢复日志对象时,我丢失了所有引用并且必须重新设置它们。必须有更简单的方法。有没有一种简单的方法来更新对象的原始副本,而无需手动运行所有这些 getter 和 setter?似乎这应该更容易......我正在使用 getInstance 等将日志实现为 Sington。
    • @PrecisionPete - 在 UI 仍处于活动状态时,您的单例如何需要恢复?如果 UI 也在重建,为什么它会跳过最初建立链接的代码?最好将此问题标记为已解决并发布一个新问题,显示相关代码和问题的详细描述。
    猜你喜欢
    • 1970-01-01
    • 2014-05-09
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    相关资源
    最近更新 更多