我遇到的问题与in this discussion类似:我需要在底层数据库发生更改时刷新ListView,但查询很昂贵,所以我在AsyncTask中这样做。
这是我更新的Cursor准备好后所做的事情。 (这也是最初在启动时填充列表的方式。)
@Override
protected void onPostExecute(Cursor result) {
if (activity != null) {
if (currentCursor != null) {
// existing cursor is closed by adapter.changeCursor() so
// we don't need to explicitly close it here
stopManagingCursor(currentCursor);
}
currentCursor = result;
startManagingCursor(currentCursor);
if (adapter == null) {
adapter = getAdapter(result);
setListAdapter(adapter);
} else {
adapter.changeCursor(result);
}
activity.onGotList(result, dbAdapter);
}
}
这是我得到的错误。它不会每次都发生,这更令人沮丧。
Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: SELECT DISTINCT t._id AS _id, t.amount, t.date, t.memo, t.synced, t.flag, (children.pa
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:100)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:46)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1412)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1382)
所以,我显然没有正确关闭Cursor。如果我调用currentCursor.close()
而不是依赖于由adapter.changeCursor()
关闭的传出Cursor,那么我会收到关于关闭Cursor两次或关闭null
光标的警告。
这样做的正确方法是什么?
在我与之相关的讨论中,Dianne Hackborn建议使用Loader
代替。这不是我的选择,因为我的代码必须在Android 2.1上运行。
答案 0 :(得分:0)
当Activity暂停或终止时,尝试.close()Cursor。 在活动的onPause()或onDestroy()部分。
答案 1 :(得分:0)
基本上,从两个不同的帮助程序访问同一个数据库是可能的,但是非常糟糕的做法,所以如果你有一个执行数据库查询的活动,你不应该有一个线程访问它,否则android会抛出一个安静在logcat中出错,然后忘记查询...
我找到的最佳解决方案是实现一个runnables的线程池,每个都是一个数据库查询,它们都使用相同的数据库帮助器。因此,任何时候只有一个线程正在访问数据库,并且在线程池启动/停止时只打开和关闭数据库。
可以在此处找到线程池模式的实现:http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/
答案 2 :(得分:0)
如果您没有更改任何其他内容,则从列表中重新绘制是必须更改光标。你能不能只需要当前的适配器就可以了。
的内容
adapter.getCursor().requery();
虽然如果你在主线ui线程之外的其他线程,你可能想用
来调用它//Did not realize this was deprecated Thanks to Graham Borland for the heads up
runOnUiThread(new Runnable(){
public void run(){
adapter.getCursor().requery();
}
});
取决于您的设置。
新解决方案仍然需要测试,并确保它不会导致问题显然startManaginCursor和stopManaginCursor也被弃用,所以这个解决方案也不值得。
stopManagingCursor(adapter.getCursor());
if (!adapter.getCursor().isClosed())
adapter.getCursor().close();
//cursor creation stuff here if needed
startManagingCursor(newCursor);
adapter.changeCursor(newCursor);