1

我目前正在编写我的第一个 Android 应用程序,并且我的大部分知识都基于 Android 记事本教程:

http://developer.android.com/resources/tutorials/notepad/notepad-ex3.html

在我的应用程序中,我在一个 Activity 中使用了多个 DBHelper,并不是每个 Cursor 都由带有 startManagingCursor() 的 Activity 管理。

我了解到每个数据库连接都必须正确打开和关闭:

SQLiteOpenHelper.open();
Cursor.open();
//use cursor
Cursor.close();
SQLiteOpenHelper.close();

据我所知 startManagingCursor() 为您工作。但是 startManagingCursor() 是否也打开和关闭 SQLiteOpenHelper?

Android Notepad 教程使用 startManagingCursor() 但 DBHelper 从未关闭。为什么 SQLiteOpenHelper 永远不会关闭?

编辑:

这是我当前的代码。它使用一个名为 mDriverDbHelper 的 SQLiteOpenHelper。此代码是从教程中采用的:

私有 DriverDbAdapter mDriverDbHelper;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.bus_selectuser);
    mDbHelper = new DbAdapter(this);
    mDbHelper.open();
    mDbHelper.close();
    mDriverDbHelper = new DriverDbAdapter(this);
    Log.w("BuerBusActivity", "opening DB connection via DbHelber now");

    mDriverDbHelper.open();
    fillData();

    //request the screen to stay on
    this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

@Override
public void onRestart() {
    super.onRestart();

    Log.v(TAG, "onRestart");
}

@Override
public void onStart() {
    super.onStart();
    mDriverDbHelper.open();
    Log.v(TAG, "onStart");
}

@Override
public void onResume() {
    super.onResume();
    Log.v(TAG, "onResume");
}

@Override
public void onPause() {
    Log.v(TAG, "onPause");
    super.onPause();
}

@Override
public void onStop() {
    mDriverDbHelper.close();
    Log.v(TAG, "onStop");
    super.onStop();
}

此代码示例确实有效,但我不明白为什么。我在 onCreate 和 onStart 中两次调用 mDriverDBHelper.open()。

我试图将 open() 和 close() 调用放在 onPause 和 onResume 中,但这会导致错误:

Cursor: invalid statement in fillWindow()

有谁知道为什么它必须是 onStart 和 onStop 而不是 onPause 和 onResume?

最终答案

本教程缺少 close() 方法调用。结合活动生命周期使用 open 和 close 的一般规则是:

在活动生命周期方法中打开 SQLiteOpenHelper 后,您应该在相应的对应生命周期方法中关闭它。

@Override
public void onCreate() {
    ....
    //open SQLiteOpenHelper
    onCreateHelper.open();
}

@Override
public void onStart() {
    ....
    //open SQLiteOpenHelper
    onStartHelper.open();
}

@Override
public void onResume() {
    ....
    //open SQLiteOpenHelper
    onResumeHelper.open();
}

@Override
public void onPause() {
    ....
    //close SQLiteOpenHelper
    onResumeHelper.close();
}

@Override
public void onStop() {
    ....
    //close SQLiteOpenHelper
    onStartHelper.close();
}

@Override
public void onDestroy() {
    ....
    //close SQLiteOpenHelper
    onCreateHelper.close();
}

在 Android NotePad 教程中,缺少 onDestroy() 方法,应该关闭 mDbHelper。

4

3 回答 3

2

根据startManagingCursor文档,它只处理游标。所以我相信它对数据库连接没有任何作用,因为它将来可能需要重新查询数据。

从 Android 开发者的网站:

此方法允许活动根据活动的生命周期为您管理给定游标的生命周期。也就是说,当活动停止时,它会自动在给定的光标上调用deactivate() ,当它稍后重新启动时,它会为你调用 requery()。当活动被销毁时,所有托管游标将自动关闭。

关于 android notepad 教程中的数据库连接关闭,我认为他们错过了在示例代码中关闭它。所以没什么大不了的:)

于 2012-04-03T15:25:09.250 回答
0

对于它的价值,示例代码也没有处理用户点击设备的后退按钮的真正可能性。这可能会导致空指针通过 bundle extras 传递。为了防止示例崩溃,您可以在 super 调用之后将 try / catch 块包裹在所有内容中,如下所示:

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
        try {
              Bundle extras = intent.getExtras();

              switch(requestCode) {
              case ACTIVITY_CREATE:
                     String title = extras.getString(NotesDbAdapter.KEY_TITLE);  
                              // ^^^ LATER down goes KA-BOOM !
               // etc ... as in sample
              } // end switch stmt
         } catch (Exception e ) {
          Log.d ( "onActivityResult caught exception: ", e.toString() ) ;
         } // end try / catch
    // ...   

就像 C/C++ 似乎null的东西是 Java 中最常见的错误......

于 2013-03-05T03:34:18.760 回答
0

永远不要关闭 DbHelper 旨在永远保持打开状态。

并且不要关闭getReadableDatabase()和getWritableDatabase()的结果,即使是最优条件下的同一个对象。

检查源代码,连程序员都不喜欢:

private SQLiteDatabase getDatabaseLocked(boolean writable) {
    if (mDatabase != null) {
        if (!mDatabase.isOpen()) {
            // Darn!  The user closed the database by calling mDatabase.close().
            mDatabase = null;
        } else if (!writable || !mDatabase.isReadOnly()) {
            // The database is already open for business.
            return mDatabase;
        }
    }
...
}

为了稳定和加快使用事务,请检查: http ://tech.vg.no/2011/04/04/speeding-up-sqlite-insert-operations/

于 2013-07-24T02:21:15.263 回答