アプリにデータベースがあり、何かを挿入または削除する必要がある場合は、もちろんデータベースを開く必要があります。私はこれをすべてのアクティビティで行うので、データベースが開いていてもデータベースを開くことを意味します。DDMSでは、「リークが見つかりました」と表示されます。データベースを一度だけ開くにはどうすればよいですか?シングルトンクラスを使用する必要がありますか?
2 に答える
はい、シングルトンが最適なオプションです。共通インスタンスを使用してデータベースにアクセスできます。DBを外部アクティビティと共有する場合は、コンテンツプロバイダーにアクセスしてください。
これは、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()
で、システムがすべてを処理します(つまり、複数のインスタンスが作成されないようにシングルトンパターンを設計する必要はありません)。
お役に立てば幸いです。