3

Androidで作業するときにデータベース接続を作成および使用する方法に関するブログやチュートリアルをたくさん読みました。実用的な例はたくさんありますが、実装が異なれば問題も異なります。

例として、データソース クラスDatasourceとデータベース ヘルパー クラスを使用しますDBManagement

情報源

public class DataSource {
    // Database fields
    private SQLiteDatabase database;
    private DBManagement dbHelper;

    public SMSDataSource(Context context) {
        dbHelper = new DBManagement(context);
    }

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

public Cursor exampleCursor(long constraint){
    Cursor cur = database.query(DBManagement.TABLE_NAME,
            new String[] {DBManagement.Column}, "constraint="+constraint, null, null, null, null);
    return cur;
}
    //.. other methods down here which do rawQuery, QueryBuilder, etc.. 

DB管理

public class DBManagement extends SQLiteOpenHelper{

    // .. table definitions and columns etc ..//

    public DBManagement(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);      
    }

アクティビティ内の onCreate メソッドで呼び出しdatasource.open()、SQL 接続が開かれます。その後、私はやります:

DataSource datasource = new DataSource();

Cursor cursor = datasource.exampleCursor(1);
startManagingCursor(cursor);

新しいアクティビティに移動すると、次のエラーが発生します。

 06-27 21:59:14.812: E/Database(13396): close() was never explicitly called on database '/data/data/com.example.package/databases/db.db' 

datasource.close();onCreate の最後に追加すると、単純なカーソル アダプタが機能しなくなります。または、コンテキスト メニューでアクションを実行すると、データベースが開いていないというエラーが発生します。

上記を処理する最良の方法は何ですか?

だから私は次のことをしましたが、まだデータベースの問題が発生しています:

@Override
public void onBackPressed() {
    // do something on back.
    //Log.i(getClass().toString(), "onBackPressed");

    datasource.close();

    finish();
    return;
}

@Override
protected void onResume(){
    super.onResume();
    onCreate(null);
}


@Override
protected void onRestart(){
    datasource = new DataSource(this);
    datasource.open();

    filters = datasource.getFilterCursor();
    startManagingCursor(filters);

    super.onRestart();
}

@Override
protected void onPause(){
    //Log.i(getClass().toString(), "onPause");
    ((CursorAdapter) adapter).getCursor().close();
    datasource.close();
    super.onPause();
}   
@Override
protected void onStop(){
    //Log.i(getClass().toString(), "onStop");
    datasource.close();
    super.onStop();
}

私のDatasource.javaクラスには次のものがあります。

public Datasource(Context context){
     dbHelper = new DBManagement(context);
}

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

public void close(){
    if(dbHelper != null){
         dbHelper.close();
    }
}
4

5 に答える 5

5

これは実際には非常に簡単です。

  • 完了したら、すべてのカーソルを明示的に閉じます(を使用finally)など。
  • 使用しないでくださいstartManagingCursor()
  • データベースラッパー/ヘルパー/マネージャー/クラスをシングルトンにする
  • データベース ヘルパーclose()を明示的に呼び出さないでください。あなたのプロセスが死ぬと、私は自動的に閉じられます。

さらに、頻繁に開いたり閉じたりすることは、かなりのオーバーヘッドがかかるため、間違いなく悪い考えです。

ローダーの使用もオプションです。ローダーを使用するためにコンテンツ プロバイダーを使用する必要はありませんが、それほど単純ではありません。コンテンツ プロバイダーの使用には IPC が含まれますが、データを他のアプリにエクスポートする予定がない場合、通常はやり過ぎです。

于 2012-07-19T04:03:30.163 に答える
4

問題の「理想的な」解決策は、 と に移行しContent Providers、下位互換性のために互換性ライブラリをLoaders使用することです。v4そうすることで、データベース接続を開いたり閉じたりする必要がなくなり、UI スレッドではなくバックグラウンドでデータベース操作を実行できるため、この問題が解決されます。

また、startManagingCursor非推奨であるため、アプリケーションの将来の証明にもなります。今のところ、4.1 でもまだ使用できますが、いずれ削除される予定です。

ここにコンテンツ プロバイダーの使用に関する別の投稿があり、プロバイダーを使用する他の理由について説明し、チュートリアルへのリンクを提供しています。

Google 側の最大の失敗は、ContentProviderそれらを構築するための簡単で直感的な方法が提供されていないことだと思います。

于 2012-06-29T13:36:53.860 に答える
4

でデータベースを開くと、でonCreate閉じることができますonDestroy

于 2012-06-29T13:24:25.893 に答える
2

データベースからのデータのフェッチが完了したら、すぐに DB 接続を閉じることを強くお勧めします。onResume()また、 と の中で開閉し直すのがベストでしょうonPause()

于 2012-06-29T13:31:19.877 に答える
2

同様の問題があったことを覚えており、古い参照を閉じずに新しいアクティビティで getWritableDatabase() を呼び出すたびにエラーを再現しました。SQLiteDatabase オブジェクトdatabase SQLiteOpenHelper オブジェクトを閉じると、dbHelperこれらのエラーが表示されなくなりました。

public void close() {
    // Check against the database being created but not opened, close writable db
    if(database != null) {
        database.close();
        database = null;
    }

    // In case someone calls DataSource.close() more than once...
    if(dbHelper != null) {
        dbHelper.close();
        dbHelper = null;
    }
}

それが役立つことを願っています!

于 2012-07-21T17:10:34.720 に答える