Singletonデータベース:アプリとサービスの両方から働くときは、「すでに閉じたオブジェクトを再開しようとしました.SQLitedatabase」
-
21-12-2019 - |
質問
だから私は同じプロセスから実行されている2つのコンテキスト(サービスとUIの活動)を持っています、そしてまた私は伝統的な包まれた方法を使って書き込みハンドルを取得します:
package me.soexample.sobad;
import java.util.concurrent.atomic.AtomicInteger;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DatabaseManager {
private static AtomicInteger mOpenCounter = new AtomicInteger();
private static DatabaseManager instance;
private static DatabaseHelper mDatabaseHelper;
private SQLiteDatabase mDatabase;
public static synchronized void initializeInstance(DatabaseHelper helper) {
if (instance == null) {
instance = new DatabaseManager();
mDatabaseHelper = helper;
}
}
public static synchronized DatabaseManager getInstance() {
if (instance == null) {
throw new IllegalStateException(DatabaseManager.class.getSimpleName() +
" is not initialized, call initializeInstance(..) method first.");
}
return instance;
}
public SQLiteDatabase openDatabase() {
if(mOpenCounter.incrementAndGet() == 1) {
// Opening new database
mDatabase = mDatabaseHelper.getWritableDatabaseAlt();
}
return mDatabase;
}
public void closeDatabase() {
if(mOpenCounter.decrementAndGet() == 0) {
// Closing database
mDatabase.close();
}
}
}
.
予想できないかのように、それはしばしば結果:
04-11 04:24:51.738: E/gsmspy(24331): java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /storage/sdcard0/my.db
04-11 04:24:51.738: E/gsmspy(24331): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
04-11 04:24:51.738: E/gsmspy(24331): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1310)
04-11 04:24:51.738: E/gsmspy(24331): at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
04-11 04:24:51.738: E/gsmspy(24331): at me.soexample.sogood.somethod2(sogood.java:51)
04-11 04:24:51.738: E/gsmspy(24331): at me.soexample.sogood.somethod(sogood.java:41)
.
わかるように、DatabaseManagerへの参照はありません。そのため、マルチスレッドの問題があるようです。 さて、そのようなラッパーから返されたDBオブジェクトに書き込まれる保証の能力を持つために何をしますか?
解決
オリジナル(「アプローチ#2」を参照)クラスはスマートなものでした。 さて、DatabaseManager()でデータベースヘルパー(SQLiteOpenHelper)が構築され、問題を削除しています(これ以上2つのSQLiteOpenHelperの並列ワーストケースで動作する)
所属していません StackOverflow