对 SQLite 数据库使用单例设计模式点击这里查看我关于这个主题的博客文章。

我在Android上相当新手,我正在开发一个简单的应用程序来获得一些基本体验。我的应用程序非常简单,包括广播接收器和一些活动。这两个组件都使用单个数据库,因此从理论上讲,两者都可能尝试同时访问数据库。

目前,我只是在每次需要时实例化数据库对象(即 SQLite db 帮助程序类),并执行所需的操作:查询、插入等。

根据我在这里和其他一些文档中阅读的内容,如果同时访问数据库,这存在“db锁定”异常的问题,因此更好的方法是拥有此数据库对象的单个实例,以便所有组件始终使用相同的数据库连接。

上述推理是否正确?那么,单例会是一个足够好的解决方案吗?我知道一些纯粹主义者可能会反对它,但请注意,这是一个相当简单的应用程序,所以我可以负担得起做一些在其他情况下我不会做的事情。

否则,更好的选择是什么?我已经阅读了有关使用内容提供商的信息,但这样做会太多,除此之外,我对与其他活动共享数据不感兴趣。我确实读过这篇文章,发现它很有帮助。


答案 1

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


下面是一些示例代码,用于说明三种可能的方法。这些将允许在整个应用程序中访问数据库。

方法#1:让'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://android-developers.blogspot.nl/2009/01/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;
    }
}

方法#2:使用“内容提供者”抽象SQLite数据库

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

希望这有帮助!


答案 2

我从来没有读过关于使用单例在android上访问数据库的信息。您是否介意提供有关该内容的链接。

在我的应用程序中,我使用简单的dbhelper对象,而不是单例,我认为这更像是sql引擎的工作,以确保db不被锁定,而不是你的Android类的工作,它适用于我最大的中型应用程序。

更新#1:查看您提供的参考,看起来问题根本不在于使用.即使是单个实例也可能在访问数据库时遇到问题:问题来自并发访问。因此,确保不同线程正确访问数据库的唯一方法是使用简单的线程同步机制(方法或块),这与使用单例几乎没有关系。dbhelpersynchronized

更新#2 :您提供的第二个链接清楚地表明,在数据库中同时写入多个线程的情况下,需要单例dbhelper对象。例如,如果您从AsyncTasks执行sql操作(插入/更新/删除),则可能会发生这种情况。在这种情况下,单例对象 dbhelper 会简单地将所有 sql 操作放在某种管道中,并按顺序执行它们。

与在 java 中使用同步方法使用正确的线程同步相比,此解决方案可能更容易实现。实际上,我认为在Android文档中应该有更多关于这个问题的强调,并且可以鼓励使用单例数据库助手。

感谢您的这个好问题和后续工作。


推荐