6

したがって、すべてのアプリケーションアクティビティに対して1つのデータベースインスタンスが必要です。私は次のコードを見つけました:

public class MyApplication extends Application {

    private static SQLiteDatabase mDB = null;

    @Override
    public void onCreate() {
        super.onCreate();
    DataBaseOpenHelper m_OpenHelper = new DataBaseOpenHelper( this );
    mDB = m_OpenHelper.getWritableDatabase();
    }

    public static SQLiteDatabase getDB() {
        return mDB;
    }
}

SQLiteDatabaseインスタンスをいつ閉じることができるかわかりません。

4

3 に答える 3

13

これは、Androidを初めて使用したときの問題でした。アプリケーション全体でデータベースへのアクセスを正しく許可する方法を説明するチュートリアルがウェブ上にあまりないためです(理由は聞かないでください)。これは、3つの可能なアプローチを示すサンプルコードです。

アプローチ#1:`アプリケーション`のサブクラス化

アプリケーションがそれほど複雑にならないことがわかっている場合(つまり、のサブクラスが1つしかないことがわかっている場合Application)、のサブクラスを作成しApplicationて、メインのアクティビティに拡張させることができます。これにより、データベースの1つのインスタンスがアプリケーションのライフサイクル全体で確実に実行されます。

public class MainApplication extends Application {

    /**
     * see NotePad tutorial for an example implementation of DataDbAdapter
     */
    private static DataDbAdapter mDbHelper;

    /**
     * create the database helper when the application is launched 
     */
    @Override
    public void onCreate() {
        mDbHelper = new DataDbAdapter(this);
        mDbHelper.open();
    }

    /** 
     * close the database helper when the application terminates.
     */
    @Override
    public void onTerminate() {
        mDbHelper.close();
        mDbHelper = null;
    }

    public static DataDbAdapter getDatabaseHelper() {
        return mDbHelper;
    }
}

アプローチ#2:`SQLiteOpenHelper`を静的データメンバーにする

DatabaseHelperこれは完全な実装ではありませんが、クラスを正しく設計する方法についての良いアイデアを提供するはずです。静的ファクトリメソッドは、常に1つのDatabaseHelperインスタンスのみが存在することを保証します。

/**
 * create custom DatabaseHelper class that extends SQLiteOpenHelper
 */
public class DatabaseHelper extends SQLiteOpenHelper { 
    private static DatabaseHelper mInstance = null;

    private static final String DATABASE_NAME = "databaseName";
    private static final String DATABASE_TABLE = "tableName";
    private static final int DATABASE_VERSION = 1;

    private Context mCxt;

    public static DatabaseHelper getInstance(Context ctx) {
        /** 
         * use the application context as suggested by CommonsWare.
         * this will ensure that you dont accidentally leak an Activitys
         * context (see this article for more information: 
         * http://developer.android.com/resources/articles/avoiding-memory-leaks.html)
         */
        if (mInstance == null) {
            mInstance = new DatabaseHelper(ctx.getApplicationContext());
        }
        return mInstance;
    }

    /**
     * constructor should be private to prevent direct instantiation.
     * make call to static factory method "getInstance()" instead.
     */
    private DatabaseHelper(Context ctx) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.mCtx = ctx;
    }
}

アプローチ#3:`ContentProvider`でSQLiteデータベースを抽象化する

これが私が提案するアプローチです。1つは、新しいLoaderManagerクラスがContentProvidersに大きく依存しているため、アクティビティまたはフラグメントを実装する場合LoaderManager.LoaderCallbacks<Cursor>(これを利用することをお勧めします。これは魔法のようなものです)、ContentProviderアプリケーションにを実装する必要があります。さらに、ContentProvidersを使用してシングルトンデータベースヘルパーを作成することを心配する必要はありません。アクティビティから呼び出すだけgetContentResolver()で、システムがすべてを処理します(つまり、複数のインスタンスが作成されないようにシングルトンパターンを設計する必要はありません)。

お役に立てば幸いです。

于 2012-02-14T23:57:55.693 に答える
2

あなたは本当にそれを閉じる必要はありません。プロセスが終了すると、自動的に閉じられます。Applicationオブジェクトを使用する代わりに、DBヘルパーオブジェクトをシングルトンにして、簡単にアクセスできるようにすることができます。ところで、getWritableDatabase()そしてgetReadableDatabase()それほど違いはありません。唯一の違いは、スペースが不足している場合に機能するgetReadableDatabase() 可能性がある一方で、もう一方は例外をスローすることです。

于 2011-09-02T02:12:43.627 に答える
0

DataBaseOpenHelperのグローバルインスタンスを作成し、実際にDBが必要なポイントでgetWritableDatabase()を呼び出すことができれば、これは推奨されないと思います。そして明らかに、必要なときにのみ書き込み可能なインスタンスを取得します。それ以外の場合は、getReadableDatabase()を使用します。

この背後にある正確な理由はわかりませんが、これは取得および/または保持するのに高価なオブジェクトであるため、アプリがロードされてグローバルインスタンスを保持するときに作成したくないと思います。多分誰か他の人がこの点を明確にすることができます。私もこれを行う衝動を持っていたので、Androidドキュメントがこれをよりよく説明することを望みます。

于 2011-09-01T22:26:49.390 に答える