10

正常に機能し、強制終了またはクラッシュしないアプリがあります。しかし、LogCat を見ると、ときどき次のように表示されます。

05-20 15:24:55.338: E/SQLiteDatabase(12707): close() was never explicitly called on database '/data/data/com.---.--/databases/debt.db' 
05-20 15:24:55.338: E/SQLiteDatabase(12707): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here

少し下...

05-20 15:24:55.338: E/System(12707): Uncaught exception thrown by finalizer
05-20 15:24:55.338: E/System(12707): java.lang.IllegalStateException: Don't have database lock!

データベースを開いたり閉じたりするタイミングがわかりません。

単なるスプラッシュ スクリーンである Main アクティビティがあります。次に、DB からの情報を使用して ListView を呼び出すアクティビティに入ります。したがって、DB が最初に開かれるのはこのアクティビティです。

ListView を使用して分岐する DB が必要な別のアクティビティもあります。これをいつ開いて閉じることになっていますか?一度開くだけで、アプリが「一時停止」、「停止」、または「破棄」されたときに閉じる必要があるようです。

この場合、db.close() メソッドをどこに配置しますか... onStop などが配置されているスプラッシュ スクリーンのメイン アクティビティに配置しますか? またはDBを開くアクティビティと同じですか?または..別の場所はありますか?

アップデート:

これは、エラーが指し続けるコードの行です。

public void open() throws SQLException {
    database = dbHelper.getWritableDatabase();
}
4

3 に答える 3

9

DatabaseHelper クラスのインスタンスを使用していて、DBHelper オブジェクトを初期化した後、データベースで作業を行うたびに、作業を行う前に open メソッドを呼び出す必要があります。その後、新しいカーソルを作成し、データベースにクエリを実行して、カーソルに保存したばかりの情報を操作し、完了したらカーソルを閉じ、データベースを閉じます。たとえば、データベース内のすべてのアイテムを取得したい場合は、次のようにします。

...    
DataBaseHelper db = new DataBaseHelper(this);
... 
db.open();
Cursor cursor = db.getAllItems(); 
maxCount = cursor.getCount(); 
Random gen = new Random();
row = gen.nextInt(maxCount); // Generate random between 0 and max
if (cursor.moveToPosition(row)) {
    String myString = cursor.getString(1);  //here I want the second column
    displayString(myString); //private method
}
cursor.close();
db.close(); 

getAllItemsは my のパブリック メソッドDatabaseHelperです。

public Cursor getAllItems() {
    return db.query(DATABASE_TABLE, 
        new String[] {
            KEY_ROWID, 
            KEY_NAME
        }, 
        null, 
        null, 
        null, 
        null, 
        null);
}

これが私のデータベースへのアクセス方法であり、エラーはまったく発生しておらず、完全に機能しています。

于 2012-05-20T23:25:29.183 に答える
3

私は@Sikimaが上記の方法で行っていましたが、多くのバックグラウンドサービス、マルチスレッドなどを持つ複雑なアプリケーションでは、多くのデータベースインスタンスを管理し、さらにそれらを開いたり閉じたりする必要がある場合、本当に面倒になることがあります。

これを克服するために、次の方法を使用しましたが、うまく機能しているようです。

1.

次のように、Application基本クラスでYourDBHelperClassのインスタンスを宣言して初期化します。

public class App extends Application {
  public static YourDBHelperClass db;

  @Override
  public void onCreate() {
    super.onCreate();
    db = new YourDBHelperClass(getApplicationContext());
    db.open();

  }
}

2.

アクティビティ、または DB を使用するその他の場所で、次のように YourDBHelperClass オブジェクトを初期化します。

YourDBHelperClass db = App.db;

そして、毎回手動で開いたり閉じたりすることを心配することなく、好きなようにデータベースを使用できます。SQLiteOpenHelperは、アプリケーションが破棄されたときに終了を処理します

于 2014-03-11T05:58:48.243 に答える
2

データベースを正しく処理していない可能性があります。閉じているよりも多くのデータベース インスタンスを開いています。

この動作を修正するために従うことができる多くの設計パターンがあります。詳細については、この回答を参照してください。

于 2012-05-20T23:24:19.987 に答える