是否可以让一个 SQLiteOpenHelper 实例由 Android 应用程序中的所有活动共享?点击这里查看我关于这个主题的博客文章。

是否可以将 SQLiteOpenHelper 的单个实例作为子类应用程序的成员,并让所有需要 SQLiteDatabase 实例的活动从一个帮助程序获取它?


答案 1

点击这里查看我关于这个主题的博客文章。


CommonsWare是正确的(像往常一样)。在他的帖子中,下面是一些示例代码,说明了三种可能的方法。这些将允许在整个应用程序中访问数据库。

方法#1:子类化“应用程序”

如果你知道你的应用程序不会很复杂(即,如果你知道你最终只会有一个子类),那么你可以创建一个子类,并让你的主活动扩展它。这可确保数据库的一个实例在应用程序的整个生命周期中运行。ApplicationApplication

public class MainApplication extends Application {

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

    /**
     * Called when the application is starting, before any other 
     * application objects have been created. Implementations 
     * should be as quick as possible...
     */
    @Override
    public void onCreate() {
        super.onCreate();
        mDbHelper = new DataDbAdapter(this);
        mDbHelper.open();
    }

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

方法#2:让'SQLiteOpenHelper'成为静态数据成员

这不是完整的实现,但它应该给你一个关于如何正确设计类的好主意。静态工厂方法确保在任何时候都只存在一个数据库帮助程序实例。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:使用“内容提供者”抽象SQLite数据库

这就是我建议的方法。首先,新类在很大程度上依赖于 ContentProviders,因此,如果您希望实现 Activity 或 Fragment(我建议您利用它,这很神奇!),则需要为您的应用程序实现一个。此外,您不必担心使用 ContentProviders 创建 Singleton 数据库帮助程序。只需从 Activity 调用,系统就会为您处理所有事情(换句话说,无需设计 Singleton 模式来防止创建多个实例)。LoaderManagerLoaderManager.LoaderCallbacks<Cursor>ContentProvidergetContentResolver()

希望有所帮助!


答案 2

拥有单个实例有助于线程处理情况。因为所有的线程都共享公共的,所以提供了操作的同步。SQLiteOpenHelperSQLiteDatabase

但是,我不会创建 的子类。只需有一个静态数据成员,即可。这两种方法都可以让您从任何地方访问。但是,只有 一个子类,这使得您更难使用 的其他子类(例如,GreenDroid 需要一个 IIRC)。使用静态数据成员可以避免这种情况。但是,在实例化此静态(构造函数参数)时,请务必使用 ,这样就不会泄漏其他 .ApplicationSQLiteOpenHelperApplicationApplicationApplicationContextSQLiteOpenHelperContext

而且,在不处理多个线程的情况下,可以通过每个组件仅使用一个实例来避免任何可能的内存泄漏问题。但是,在实践中,您应该处理多个线程(例如a),因此此建议仅与琐碎的应用程序相关,例如在某些书籍中找到的应用程序... :-)SQLiteOpenHelperLoader


推荐