我正在尝试在我的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)
不起作用。我已经尝试了ArrayList
和HashMap
,看起来它们没有被序列化并写入缓存。程序执行所有代码,然后在返回之前挂起大约一分钟,只留下缓存目录中的journal
文件。
我不确定这是否是DiskLruCache无法处理容器对象的问题。
The full source and original post can be found here
编辑(2014-01-03):
Here's a JUnit test using the Android SDK。 testStoreLong()
,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兼容的替代磁盘缓存库?
答案 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()方法之后,只需将对象转换为您想要的任何类型,或者更好地更改这些方法以使用泛型来实现类型安全。