1

我不知道如何正确处理此问题而不会出现数据库锁定错误。

我的应用程序基本上以 100 行(约 60.000 个项目)的形式下载许多项目并将它们插入数据库中。每批 100 行被处理成一个事务。主要活动允许用户在下载和插入记录时在屏幕(片段)之间导航。大多数其他屏幕包含从数据库中读取的数据。我在阅读过程中遇到很多数据库锁定错误。所有读数都在不同异步任务的主要活动(不是片段)中完成

到目前为止,我只使用了“经典方法”

public class DBAdapter {
public DBAdapter(Context ctx) {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }


    private static class DatabaseHelper extends SQLiteOpenHelper {


        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);

        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DB_CREATE_TABLES);

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Utils.log("Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
            onCreate(db);
        }

    public DBAdapter open() throws SQLException {
        database = DBHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        DBHelper.close();
    }

然后在我的活动的 onCreate() 上调用db = new DBAdapter(context); ,每次我进行数据库操作(读/写)时我调用db.open(),插入/读取完成后我调用db.close()

我的问题是:

  1. 解决这种情况的最佳方法是什么?
  2. db.open考虑到我做了很多写/读操作,调用onCreate 和db.close()onDestroy()会更好吗?这会比每次我需要访问数据库时调用 open/close 更好吗?
  3. 我需要做些什么来避免读取时数据库锁定?
4

3 回答 3

0

考虑将 SQLite 数据库包装在 ContentProvider 中,并使用 CursorLoader 从各种活动和片段中进行查询。这将数据库的管理与 Activity/Fragment 生命周期隔离开来,并且可以减少许多打开/关闭周期。

您可能仍然会在读取和写入之间遇到争用,但是将所有数据库交互放在同一个模块中应该会让您更容易解决这些问题。

一些有趣的链接: http ://www.vogella.com/articles/AndroidSQLite/article.html#todo

何时使用内容提供者

于 2013-08-29T21:23:10.997 回答
0

一种非常简单的方法,或者可能是一种解决方法是使用同步方法来打开和关闭数据库对象。我真的不知道这是否是最佳做法,但至少它简单易行。将此方法添加到您的 DBAdapter 类,并使用它们代替 db.open 和 db.close。use_count 属性简单地保存了 open 被调用的次数。将其初始化为 0。此外,为了使其适用于您的解决方案,请确保在片段之间传递相同的 DBAdapter 对象。不要每次都创建一个新的:

private int use_count = 0;
public synchronized void doOpen()
{
    use_count++;
    this.open();
}

public synchronized void doClose()
{
    use_count--;
    if (use_count == 0)
    {
        this.close();
    }
}
于 2013-08-29T21:25:00.807 回答
0

我和你的情况完全一样。除了您所描述的,在我的应用程序中,用户还可以通过屏幕上的输入来更新数据库。我解决它的方式(我不知道这是否是最好的方式,但我现在几乎看不到任何锁定问题)

  • 创建一个从 SQLiteOpenHelper 派生的单例类,以确保在任何给定时间只有一个实例在运行。
  • 为插入/更新/删除/查询操作实现 ContentProvider 类。使所有这些功能“同步”
  • 仅在 ContentProvider 的关闭功能中关闭数据库。我做一个非常频繁的数据库操作,所以我不想每次都打开/关闭。但我不确定这是否是正确的处理方式。
  • 只能从任何地方通过 ContentProvider 接口访问数据库
于 2013-08-29T21:50:23.177 回答