2017-06-15 9 views
0

私は私のアプリをクラッシュした時間この迷惑なランタイムエラーを取得保管:いつSQLiteDatabaseオブジェクトを閉じるべきですか?

java.lang.RuntimeException: doInBackgroundを(実行中にエラーが発生しました)。 java.lang.IllegalStateException:によって引き起こさ

試み 再オープンに既に閉じたオブジェクト:いくつかのデバッグした後、私はonDestory()に、私は私のSQLiteDatabseオブジェクトをクローズするので、それが起こることがわかっ

をSQLiteDatabase方法。私はSQLiteOpenHelper.close()と呼んでも起こります。

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    _cursor.close(); //is fine 
    _db.close(); //causes error 
    _databaseHelper.close(); //causes error too (probably calls db.close() internally..?) 
    SharedFunctions.d("closed!"); //ignore this ugly thing 
} 

これは、2つの質問

  1. が表示されます、私はそれが正しいでしょうか?
  2. の場合は、onDestroyメソッドではない場合、SQLiteDatabaseオブジェクトを閉じる必要がありますか?

編集: DBとヘルパークラスは、静的である:

//get database helper 
     if(_databaseHelper == null) 
      _databaseHelper = SalaryDatabaseHelper.getInstance(this); 

dbAsyncTask.doInBackground()に初期化される:

public class MainActivity extends Activity { 

    private Cursor _cursor = null; 
    private MyCursorAdapter _myCursorAdapter = null; 
    private ListView _listView = null; 

    private static SalaryDatabaseHelper _databaseHelper = null; 
    public static SQLiteDatabase db = null; 

    ... 

IがのonCreateで_databaseHelper()メソッドを初期化します

protected Boolean doInBackground(Integer... data) 
{ 
    try { 
     //get writable database 
     if(db == null) 
      db = SalaryDatabaseHelper.getDbInstance(); 

Iヘルパークラスとデータベースクラスのシングルトン使用:(両方ともヘルパークラスを介してアクセス)

class MyDatabaseHelper extends SQLiteOpenHelper{ 

    private static SalaryDatabaseHelper _instance = null; 
    private static SQLiteDatabase _dbInstance = null; 

    //singletons 
    public static synchronized SalaryDatabaseHelper getInstance(Context context) 
    { 
     // Use the application context, which will ensure that you 
     // don't accidentally leak an Activity's context. 
     if (_instance == null) 
      _instance = new SalaryDatabaseHelper(context.getApplicationContext()); 

     return _instance; 
    } 

    public static synchronized SQLiteDatabase getDbInstance() { 
     if(_dbInstance == null) 
      _dbInstance = _instance.getWritableDatabase(); 

     return _dbInstance; 
    } 

    ... 
+0

「_db」とは何ですか? '_databaseHelper'とは何ですか?これらの規則的または静的なフィールドはありますか?この例外はどこで発生していますか? – CommonsWare

+0

私はいくつかのコードを追加しました – Pilpel

答えて

2

あなたSQLiteOpenHelperインスタンスstaticであり、したがって、グローバルスコープです。それを念頭に置いて:

私はそれを正しくやっていますか? (おそらくない)

するとされていない場合、私はonDestroy方法では、SQLiteDatabaseオブジェクトをクローズする必要がありますか?

SQLiteはトランザクションです。データベースのクローズに失敗してもリスクはありません。

はい、これはあまりにも私をいらだたが、私はこれ以上の悲しみの7つのステージを経ていて、私は午前アクセスして1つのコンポーネントがあり、「受諾」単純なシナリオで

へそのコンポーネントが破棄されたときにデータベースを閉じることがあります。あなたの場合、バックグラウンドスレッドを含むアプリケーション全体がデータベースにアクセスできます。その場合は、決してそれを閉じることはありません。

+0

それはいつ閉じますか?ユーザーが手動でアプリを終了した場合のみ?また、SQLiteDatabaseとSQLiteOpenHelperをstaticとして宣言するのは間違っていますか? – Pilpel

+0

@Pilpel: "それでいつ閉鎖されますか?" - 'close()'メソッドが呼び出されるという点ではそうではありません。最終的にプロセスは終了し、 'SQLiteOpenHelper'や' SQLiteDatabase'を含め、すべてのオブジェクトはなくなります。 "SQLiteDatabaseとSQLiteOpenHelperを静的として宣言するのは間違っていますか?" - '静的' 'SQLiteOpenHelper'を持っているか、他のシングルトンが' SQLiteOpenHelper'を保持していることが一般的です。私はどこでもフィールドとして 'SQLiteDatabase'を持っていません。それを取得するためにヘルパーで 'getWritableDatabase()'を呼び出します。 – CommonsWare

+0

@Pilpel:また、あなたの '静的' 'SQLiteOpenHelper'に対して、あなたは[二重チェックロッキング(https://stackoverflow.com/a/18093774/115145)を正しく実装していません。 'static'の代わりに' static volatile'フィールドを作るとOKです。 – CommonsWare

1

本当に、データベース接続を閉じる必要はありません。 データベースをアプリケーションオブジェクトのフィールドとして保存できます。

公式ドキュメントでは、データベースを閉じる時間について何も言及していません。また、this questionは、Googleエンジニア の古い(今削除された)投稿を引用しています。このアプローチは問題ありません。

そして実際のアプリケーションでは、何年もうまく機能します。

関連する問題