我正在尝试在我的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的磁盘缓存库?
最佳答案
嗯,是Jake Wharton为创建此缓存库而疯狂的道具,但我发现使用起来非常不直观,我发现的所有示例都用于图像缓存。
我已经重新创建了两种可以帮助您的方法
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()方法后,只需将对象强制转换为所需的任何类型,或者最好更改这些方法以将泛型用于类型安全。