管理Android活动中的数据库连接

时间:2009-12-28 17:47:55

标签: android sqlite

我有一个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()可以被多次调用,因为用户可以通过菜单项过滤结果(我把这部分留下了代码,因为即使用户没有过滤也会出现问题)。

同样,问题在于,当我到家时,我得到泄漏错误。然而,回家后,我可以回到应用程序并再次找到我的列表 - 光标完好无损。

5 个答案:

答案 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仍然是单身人士。查看我关于主题的博客文章:

Correctly Managing Your SQLite Database

答案 3 :(得分:0)

关闭Cursor中的SQLiteDatabaseonDestroy(),以查看尚未关闭的内容,看看是否有帮助。可能会出现isFinishing()falseonPause()的情况,但onDestroy()仍然被调用。

答案 4 :(得分:0)

通常是

onDestroy()

是您应关闭数据库并在

中打开它的位置
onCreate()