0

データベース接続を処理するための最良のアプローチを探しています。私は次の方法でアプリケーションベースを設計し、正常に動作します。ただし、特に古いモデルのデバイスでは、アプリケーションがクラッシュすることがあります。私の次の方法を見てください。

DatabaseHelperここにすべてのテーブルを作成するクラスがあります。このクラスは次のようなものです。

public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);

        Log.i(TAG, "Object created.");
    }

@Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CRT_TBL_1);
        db.execSQL(CRT_TBL_2);
        db.execSQL(CRT_TBL_3);
        db.execSQL(CRT_TBL_4);
        db.execSQL(CRT_TBL_5);
        db.execSQL(CRT_TBL_6);
        db.execSQL(CRT_TBL_7);
        db.execSQL(CRT_TBL_8);
    }

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(DatabaseHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data.");

        onCreate(db);
    }
}

ご覧のとおり、8つの異なるアクティビティのデータを提供する8つのテーブルがあります。1つのアクティビティのハンドラークラスの実装は、次のコードのようなものです。

public class DatabaseHandler_1 {

    private final String TAG = "DatabaseHandler_1 ";

    private DatabaseHelper dbHelper;
    private SQLiteDatabase database;

    public DatabaseHandler_1 (Context context) {
        dbHelper = new DatabaseHelper(context);

        Log.i(TAG, "Object created.");
    }

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

    public void close() {
        dbHelper.close();
    }

// ... Other methods insert, update, query, ...
}

最後に、必要な情報に基づいて、それらの1つまたはいくつかが各アクティビティで使用されます。

public class Activity_1 {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "Try to create activity...");

        // Creating Database/Table
        dbHandler_1 = new DatabaseHandler_1 (this);
        dbHandler_1 .open();
        dbHandler_2 = new DatabaseHandler_2 (this);
        dbHandler_2 .open();
        dbHandler_3 = new DatabaseHandler_3 (this);
        dbHandler_3 .open();
    }

     @Override
     protected void onDestroy() {
        super.onDestroy();

        // Closing database
        dbRecipesHandler.close();
        dbFavoritsHandler.close();
        dbShoppingHandler.close();
     }

        // Other methods for displaying data...
}

クラッシュが発生すると、logcatは、アプリケーションがデータベースでクエリを実行している間、接続が閉じていることを示します。シナリオは次のようになります。ユーザーは最初のアクティビティを開き、次に2番目のアクティビティに進み、次に3番目のアクティビティに進みます。これで、ユーザーが戻るボタンをクリックすると、3番目のアクティビティが閉じられ、このアクティビティのonDestroy()メソッドがデータベース接続を閉じます。2番目のアクティビティはまだメモリ内にあるため、アクティビティは接続がまだ開いていると想定し、データベースにクエリを実行するときにクラッシュが発生します。

Logcatは、次のようなメッセージを表示します。データベース接続が閉じています。クエリしたかった...

1つの解決策は、Android OSにデータベース接続を処理させる代わりに、手動で接続を開き、それを使用して手動で閉じることです。2番目の解決策は、各メソッドの接続を手動で開いたり閉じたりするHandlerクラスにあります。

あなたは何を提案しますか?何か経験はありましたか?任意の提案をいただければ幸いです。

4

2 に答える 2

0

一般に、データをコンテンツプロバイダーでラップしてから、アクティビティでローダーを使用 してデータをUIと混合することを検討することをお勧めします。大変な作業のように思われるかもしれませんが、コンテンツプロバイダーの多くの利点の中で、アクティビティ内のデータベース接続やカーソルを管理する必要はありません。(DatabaseHelperクラスは同じままであることに注意してください)

私が作成したさまざまなアプリのコンテンツプロバイダーと同様にデータを作成したので、ほとんどの場合、コンテンツプロバイダーが最適な方法だと思います。私の経験では、常に保守性と拡張性が向上していることに加えて、自分で構築するには非常にコストがかかる機能がたくさん組み込まれています。

とは言うものの、現在使用しているより直接的なアプローチを本当に好むのであれば、少なくとも、接続の開始と終了をアクティビティのライフサイクルに結び付けないでしょう。実際にデータが必要なときにのみこれらの接続を開き、そのデータを取得してから、接続自体とともにカーソルをすぐに閉じます。

于 2012-09-07T07:37:02.830 に答える
0

最後に私は問題を解決しました。活動中にデータベースを一度開くべきだと思いました。各アクティビティのonResume()メソッドでデータベースを再度開き、onDestroy()メソッドで閉じるのではなく、各アクティビティのonPause()でデータベースを閉じようとしました。

これまでのところ問題は解決しました。二度と見ないことを願っています。私が再びそれに直面した場合、答えを更新/削除します。

于 2012-09-07T10:52:08.487 に答える