数据库全局实例

发布于 2024-12-02 10:55:22 字数 468 浏览 1 评论 0原文

因此,我希望拥有一个用于所有应用程序活动的数据库实例。 我发现以下代码:

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 实例。

So I want to have one database instance for all application activities.
I found the following code:

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;
    }
}

I don`t understand when I can close SQLiteDatabase instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

始终不够 2024-12-09 10:55:22

当我第一次开始使用 Android 时,这对我来说是一个问题,因为网上没有太多教程来描述如何正确地允许在整个应用程序中访问数据库(不要问我为什么)。下面是一些示例代码,展示了三种可能的方法。

方法#1:子类化“Application”

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

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 类。静态工厂方法确保任何时候都只存在一个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 数据库

这是我建议的方法。首先,新的 LoaderManager 类严重依赖于 ContentProviders,因此如果您希望 Activity 或 Fragment 实现 LoaderManager.LoaderCallbacks(我建议您利用,这太神奇了!),您需要为您的应用程序实现一个 ContentProvider。此外,您无需担心使用 ContentProviders 创建 Singleton 数据库助手。只需从 Activity 中调用 getContentResolver() ,系统就会为您处理一切(换句话说,无需设计 Singleton 模式来防止创建多个实例)。

希望有帮助!

This was an issue for me when I first started out with Android, as there aren't many tutorials on the web that describe how to correctly allow access to your database across the entire application (don't ask me why). Here's some sample code that exhibits three possible approaches.

Approach #1: subclassing `Application`

If you know your application won't be very complicated (i.e. if you know you'll only end up having one subclass of Application), then you can create a subclass of Application and have your main Activity extend it. This ensures that one instance of the database is running throughout the Application's entire life cycle.

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;
    }
}

Approach #2: have `SQLiteOpenHelper` be a static data member

This isn't the complete implementation, but it should give you a good idea on how to go about designing the DatabaseHelper class correctly. The static factory method ensures that there exists only one DatabaseHelper instance at any time.

/**
 * 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;
    }
}

Approach #3: abstract the SQLite database with a `ContentProvider`

This is the approach I would suggest. For one, the new LoaderManager class relies heavily on ContentProviders, so if you want an Activity or Fragment to implement LoaderManager.LoaderCallbacks<Cursor> (which I suggest you take advantage of, it is magical!), you'll need to implement a ContentProvider for your application. Further, you don't need to worry about making a Singleton database helper with ContentProviders. Simply call getContentResolver() from the Activity and the system will take care of everything for you (in other words, there is no need for designing a Singleton pattern to prevent multiple instances from being created).

Hope that helps!

百变从容 2024-12-09 10:55:22

你真的不需要关闭它。当您的进程终止时它将自动关闭。您可以将数据库帮助器对象设置为单例,以便于访问,而不是使用 Application 对象。顺便说一句,getWritableDatabase()getReadableDatabase() 并没有那么不同。唯一的区别是,如果空间不足,getReadableDatabase()可能可以工作,而另一个会抛出异常。

You dont really need to close it. It will be automatically closed when your process dies. Instead of using the Application object, you can just make your DB helper object a singleton for easier access. BTW, getWritableDatabase() and getReadableDatabase() are not that different. The only difference is that getReadableDatabase() might work if you are out of space, while the other will throw an exception.

甩你一脸翔 2024-12-09 10:55:22

我认为不建议这样做,如果有的话,您可以拥有 DataBaseOpenHelper 的全局实例,并在实际需要数据库的地方调用 getWritableDatabase() 。显然,只有在需要时才获取可写实例,否则使用 getReadableDatabase()。

我不确定这背后的确切原因,但我的猜测是,这是一个获取和/或保留的昂贵对象,因此您不想在应用程序加载并保留全局实例时创建它。也许其他人可以澄清这一点。我希望 Android 文档能更好地解释这一点,因为我也有这样做的冲动。

I dont think this is recommended, if anything you could have a global instance of DataBaseOpenHelper, and call getWritableDatabase() at the points where you actually need the DB. And obviously, only get the writable instance when you need it, otherwise use getReadableDatabase().

I'm not sure exactly the reason behind this, but my guess is that this is an expensive object to get and/or hold on to, so you don't want to create it when the app loads and hold on to a global instance. Maybe someone else can clarify this point. I wish the Android docs would explain this better because I also had the impulse to do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文