如何使用JakeWharton的DiskLruCache正确读写数据?

时间:2013-12-28 20:49:46

标签: java android

我正在尝试在我的Android应用程序中使用Jake Wharton的DiskLruCache,但我似乎无法弄清楚如何使用缓存正确地序列化和反序列化对象。在基本命令行Java程序中使用以下代码:

DiskLruCache.Editor editor = null;
try {
    editor = diskLruCache.edit("objects");

    OutputStream timeOs = editor.newOutputStream(0);
    OutputStream dataOs = editor.newOutputStream(1);
    OutputStream timeBos = new BufferedOutputStream(timeOs);
    OutputStream dataBos = new BufferedOutputStream(dataOs);
    ObjectOutputStream timeOos = new ObjectOutputStream(timeBos);
    ObjectOutputStream dataOos = new ObjectOutputStream(dataBos);

    long createTime = System.currentTimeMillis();

    String str = "testString";

    ArrayList<String> list = new ArrayList<String>();
    list.add("item1");
    list.add("item2");

    timeOos.writeLong(createTime);

    // this works:
    dataOos.writeObject(str);
    // this does not work:
    //dataOos.writeObject(list);

    timeOos.close();
    dataOos.close();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (editor != null)
        try {
            editor.commit();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

timeOos.writeLong(createTime)dataOos.writeObject(str)成功将数据写入缓存,但将dataOos.writeObject(str)替换为dataOos.writeObject(list)不起作用。我已经尝试了ArrayListHashMap,看起来它们没有被序列化并写入缓存。程序执行所有代码,然后在返回之前挂起大约一分钟,只留下缓存目录中的journal文件。

我不确定这是否是DiskLruCache无法处理容器对象的问题。

The full source and original post can be found here

编辑(2014-01-03): Here's a JUnit test using the Android SDKtestStoreLong()testStoreString()testStoreArrayList()通过但testPersistArrayListSnapshot()testPersistArrayListEditor()失败。

这是一个奇怪的问题;如果我在第101行(editor.commit();)放置断点然后跳过,则缓存文件test-store-array-list.0 创建并且snapshot == null,测试失败。但是如果我在第103行(DiskLruCache.Snapshot snapshot = mDiskLruCache.get("test-store-array-list");)放置一个断点,则按预期创建 文件。

也许DiskLruCache中存在一个错误;有没有与Android兼容的替代磁盘缓存库?

2 个答案:

答案 0 :(得分:3)

问题是缓存大小太小。

我通过更改此问题解决了这个问题:

diskLruCache = DiskLruCache.open(new File("DiskLruCache"), 1, 2, 20 * 2^20);

对此:

diskLruCache = DiskLruCache.open(new File("DiskLruCache"), 1, 2, (long) (20 * Math.pow(2, 20)));

^是按位异或运算符,而不是指数运算符,因此高速缓存大小实际为20 * 2^20 == 60而不是它应该是:20 * Math.pow(2, 20) == 20971520

答案 1 :(得分:1)

嗯,是的疯狂道具给杰克沃顿创建这个缓存​​库,但我发现它使用起来非常不直观,我发现的所有例子都是用于图像缓存。

我重新创建了两个可以帮助你的方法

 public void put(String key, Object object)
    {
        DiskLruCache.Editor editor = null;
        try
        {
            editor = mDiskCache.edit(key);
            if (editor == null)
            {
            return;
            }

            ObjectOutputStream out = new ObjectOutputStream(editor.newOutputStream(0));
            out.writeObject(object);
            out.close();
            editor.commit()
        }
catch()...etc

并让你的对象再次出现

    public Object get(String key)
    {
       DiskLruCache.Snapshot snapshot;

       try
       {
            snapshot = mDiskCache.get(key);
            ObjectInputStream in = new ObjectInputStream(snapshot.getInputStream(0));
            return (Object) in.readObject();

        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }
    }

这些是非常基本的get和put方法,你的示例代码似乎有点复杂,因为我认为这可能是问题。在调用get()方法之后,只需将对象转换为您想要的任何类型,或者更好地更改这些方法以使用泛型来实现类型安全。