9

所以我想出了一些想法,我想知道它是否可以实现。

假设我有多个表(数据库模型),每个表都由某个类表示。我不会将单例模式与 open helper 一起使用,所以我创建了一些简单的类来提供数据库的单个实例。我的想法是,只要所有表都包含对 SQLiteDatabase 的引用(由 open helper 返回),它们都将使用相同的数据库实例,并且可能不需要与数据库同步工作,因为 open helper 会这样做。当最后一个表完成它的工作,GC 将收集打开的帮助程序(因为最后一个引用将是弱引用)-> finalize() 被调用,并且我在此方法期间关闭了数据库以防止来自操作系统的任何警告。我的问题是:这可行吗?它会自动关闭数据库吗?它会泄漏或抛出一些异常吗?

这是我的课:

public class DatabaseHelper {

private static WeakReference<SomeCustomOpenHelper> sDBOpenHelper;

private void notifyDBCreate(SQLiteDatabase db) {
    for (DBTable table : mTables) {
        table.onDBCreate(db);
    }
}

private void notifyDBUpgrade(SQLiteDatabase db) {
    for (DBTable table : mTables) {
        table.onDBUpgrade(db);
    }
}

public SQLiteDatabase getDatabase(boolean readOnly) {
    SomeCustomOpenHelper dbHelper = sDBOpenHelper.get();
    if (dbHelper == null) {
        dbHelper = new SomeCustomOpenHelper(context, name, factory, version, new DatabaseEventsCallback());
        sDBOpenHelper = new WeakReference<SomeCustomOpenHelper>(dbHelper);
    }
    if (readOnly) {
        return dbHelper.getReadableDatabase();
    } else {
        return dbHelper.getWritableDatabase();
    }
}

private class DatabaseEventsCallback implements IDatabaseEventsCallback {

    @Override
    public void onCreate(SQLiteDatabase db) {
        notifyDBCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db) {
         notifyDBUpgrade(db);
    }

}

interface IDatabaseEventsCallback {
    void onCreate(SQLiteDatabase db);

    void onUpgrade(SQLiteDatabase db);
}

private static class SomeCustomOpenHelper extends SQLiteOpenHelper {

    private IDatabaseEventsCallback mCB;

    public SomeCustomOpenHelper(Context context, String name, CursorFactory factory, int version, IDatabaseEventsCallback cb) {
        super(context, name, factory, version);

        mCB = cb;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        mCB.onCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        mCB.onUpgrade(db);
    }

    @Override
    protected void finalize() throws Throwable {
        this.close();
        super.finalize();
    }
}
}
4

5 回答 5

2

也没有真正知道答案,但感兴趣并查找了它。

答案在此处正确写出; http://blog.foxxtrot.net/2009/01/a-sqliteopenhelper-is-not-a-sqlitetablehelper.html

但基本上信息的核心是;

我创建了三个 SQLiteOpenHelper 类,每个表一个,尽管它们都只引用了一个数据库文件。

这就是一切崩溃的地方。Android 根据与之关联的包、数据库的名称和您提供的版本号来维护数据库的版本。包和名称决定了设备上的路径,而版本存储在设备上(某处),以便它知道何时需要调用 OpenHelper 的 onUpgrade 事件处理程序。事实证明,如果在 SQLiteOpenHelper 构造函数中,它确定数据库已经存在,它根本不会调用您的 onCreate 或 onUpgrade 方法,即使之前从未调用过进行调用的特定类。

于 2013-03-27T09:01:46.557 回答
2

当我在做一个项目时,我也遇到过同样的问题。我还怀疑静态实例是否使用了足够的内存并导致了相当大的内存泄漏。

我不确定创建弱引用是否能保证收集数据库实例。然而,一种可能的解决方法是:一旦您的所有数据库事务完成并关闭数据库,就为静态数据库实例分配一个空值。这可以确保数据库实例不再分配任何内存。

让我知道这是否有效,或者是否有更好的解决方法。

于 2013-04-04T09:56:23.850 回答
1

你可以这样做。正如您所说,锁定应该发生在 SQLite 上,而我从未听说过这方面的问题,所以您应该对此没问题。您唯一的限制是所有表都必须进入同一个数据库,因为 Android 目前只允许您拥有一个文件。

关闭数据库是另一回事,这就是为什么使用单例模式实际上很有趣(您避免一直关闭+打开)。尽管如此,使用您的方法,您只需要确保在完成后关闭数据库。就我而言,这不会自动完成。

此外,Lars Vogel 还撰写了有关 Android 中的数据库访问的非常有用且详细的文章。你可能想看看那里。http://www.vogella.com/articles/AndroidSQLite/article.html

于 2013-04-01T21:35:06.687 回答
1

您可以对所有表使用一个开放的助手。我在我的应用程序中使用单个实例也是这样。

public static synchronized DatabaseHelper getInstance(Context ctx)
    {
        if (dbhelper == null) {

            dbhelper = new DatabaseHelper(ctx);
        }

        return dbhelper ;
    }
于 2013-04-02T11:58:27.357 回答
0

我的问题是:这可行吗?它会自动关闭数据库吗?它会泄漏或抛出一些异常吗?

不,它不会自动关闭数据库,当您的应用程序需要 DATABASE 对象并且操作系统发现您的一些数据库即时处于活动状态时,Android 框架会尝试连接该对象引用(这可能是弱引用)

我不得不说,我不建议按需或临时打开和关闭 DATABASE。尽早打开数据库并在整个活动期间保持打开状态并在活动完成或暂停时关闭它总是很好的。

于 2013-04-05T06:25:35.927 回答