我有一个ListActivity的应用程序,它使用CursorAdapter作为其适配器。 ListActivity打开数据库并对CursorAdapter进行查询,这一切都很好,但是我在确定何时关闭Cursor和SQLiteDatabase时遇到了问题。
现在处理事情的方式,如果用户完成活动,我关闭数据库和光标。然而,这仍然最终导致DalvikVM警告我,我已经打开了数据库 - 例如,如果用户点击“主页”按钮(将活动留在任务的堆栈中),而不是“后退”按钮。
如果我在暂停期间关闭它们然后在恢复期间重新查询,那么我不会收到任何错误,但是如果用户没有重新查询(从而丢失用户在列表中的位置),用户就无法返回列表。我的意思是,用户可以点击列表中的任何项目并根据它打开一个新活动,但通常会在之后“返回”并返回列表中的相同位置。如果我重新查询,那么我无法将用户返回到正确的位置。
处理此问题的正确方法是什么?我希望列表保持正确滚动,但我不希望VM继续抱怨未关闭的数据库。
编辑:以下是我目前如何处理代码的大致概述:
public class MyListActivity extends ListActivity {
private Cursor mCursor;
private CursorAdapter mAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCursorAdapter(this);
setListAdapter(mAdapter);
}
protected void onPause() {
super.onPause();
if (isFinishing()) {
mCursor.close();
}
}
protected void onDestroy() {
super.onDestroy();
mCursor.close();
}
private void updateQuery() {
// If we had a cursor open before, close it.
if (mCursor != null) {
mCursor.close();
}
MyDbHelper dbHelper = new MyDbHelper(this);
SQLiteDatabase db = dbHelper.getReadableDatabase();
mCursor = db.query(...);
mAdapter.changeCursor(mCursor);
db.close();
}
}
updateQuery()
可以被多次调用,因为用户可以通过菜单项过滤结果(我把这部分留下了代码,因为即使用户没有过滤也会出现问题)。
同样,问题在于,当我到家时,我得到泄漏错误。然而,回家后,我可以回到应用程序并再次找到我的列表 - 光标完好无损。
答案 0 :(得分:2)
我的每个应用通常只有一个SQLiteOpenHelper
:
public class MyApp extends Application {
private static MyDbHelper dbHelper;
@Override
public void onCreate() {
super.onCreate();
dbHelper = new MyDbHelper(this);
}
@Override
public void onTerminate() {
super.onTerminate();
dbHelper.close();
}
public static SQLiteDatabase getDB() {
return dbHelper.getWritableDatabase();
}
}
到目前为止,这种方法没有任何问题
您可以使用startManagingCursor(..)
子类中提供的Activity
(尽管我让Adapter
管理Cursors
):
public class SomeAdapter extends CursorAdapter {
public void setNewFilter(CharSequense query){
// in fact, I use a DAO here
Cursor c = MyApp.getDB().query(..);
changeCursor(c);
}
}
答案 1 :(得分:1)
我不同意。看一下android文档,特别是这个图像http://developer.android.com/images/activity_lifecycle.png我会说应该在onstart()方法中创建资源并在onstop()方法中清理。这就是谷歌在代码google analytics docs for android
中处理它的方式答案 2 :(得分:1)
我建议使用抽象工厂方法来确保您的SQLiteDatabase
仍然是单身人士。查看我关于主题的博客文章:
答案 3 :(得分:0)
关闭Cursor
中的SQLiteDatabase
和onDestroy()
,以查看尚未关闭的内容,看看是否有帮助。可能会出现isFinishing()
中false
为onPause()
的情况,但onDestroy()
仍然被调用。
答案 4 :(得分:0)
onDestroy()
是您应关闭数据库并在
中打开它的位置onCreate()