为什么DBHelper在Android记事本教程中没有关闭?

时间:2012-04-03 15:14:26

标签: android sqliteopenhelper

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

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

在我的应用程序中,我在一个Activity中使用多个DBHelpers,而不是每个Cursor都由具有startManagingCursor()的活动管理。

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

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。

3 个答案:

答案 0 :(得分:2)

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

  

来自Android Developer的网站:

     

此方法允许活动负责管理给定的活动   Cursor基于活动生命周期的生命周期。那是,   当活动停止时,它将自动调用停用()   在给定的Cursor上,以及稍后重新启动它将调用    requery()为您服务。当活动被销毁时,所有托管游标都会被破坏   将自动关闭。

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

答案 1 :(得分:0)

对于它的价值,示例代码也没有处理用户点击设备的后退按钮的真实可能性。这可能会导致通过bundle extras传递空指针。为了防止样本崩溃,您可以在超级调用之后将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中最常见的错误......

答案 2 :(得分: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/