android - 在创建与 SQLite 数据库交互的方法/Activity 时,我应该多注意线程安全?

标签 android sqlite

我正在创建一个允许许多不同的应用程序 ActivitiesTabActivity 开始(最多约 25 个)。大多数 Activity 都需要来自 sqlite 数据库的数据,所以当 onCreate运行,一个AsyncTask创建一个 SQLiteOpenHelper 对象(它将打开一个可读/可写数据库),运行查询,检索数据,然后关闭所有内容。

我只是想弄乱一下看看我是否可以破坏某些东西,所以我添加了每个 ActivityTabActivity's TabHost .然后我开始尽可能快地混合每个选项卡。

我注意到我很快就开始在 LogCat 中看到:Caused by: android.database.sqlite.SQLiteException: database is locked: BEGIN EXCLUSIVE;然后该应用程序继续死亡。

对于 TabHost,通常只有大约 4-6 个选项卡(无论如何我可以限制用户) .我无法通过少量选项卡来破坏任何东西,但我仍然担心我访问数据库的方式可能很糟糕。

如何防止我的 SQLiteDatabase 对象导致锁定?

如果我创建一个 ContentProvider这会消除数据库锁定的可能性吗?

对于我可以为从 SQLiteDatabase 访问数据所做的更改,您有什么建议吗? ?

我最终采用了使用 Application 的方法类和存储 1 SQLiteOpenHelper并尽力保持同步。这似乎工作得很好——我把我所有的 25 个 Activity 都放在 TabHost 中并毫无错误地将它们混搭在一起。

我调用 ((SQLiteDbApplication)getApplication()).setDbHelper(new DBHelper(this, Constants.DB_NAME, null, Constants.DB_VERSION_CODE));每个 onCreate() 中的方法(如下所示)在我的 Activity 中

对这种方法或我使用此 Application 所做的更改的任何进一步建议类(class)?

import android.app.Application;
import android.database.sqlite.SQLiteDatabase;

public class SQLiteDbApplication extends Application {
    private DBHelper dbHelper;
    private SQLiteDatabase db;
    public synchronized DBHelper getDbHelper() {
        db = dbHelper.getDatabase();//returns the already opened database object
        while(db.isDbLockedByCurrentThread() || db.isDbLockedByOtherThreads());
        return dbHelper;
    }
    public synchronized void closeDb() {
        if(null != dbHelper)
            dbHelper.close();
        if(null != db)
            db.close();
    }

    @Override
    protected void finalize() throws Throwable {
        if(null != dbHelper)
            dbHelper.close();
        if(null != db)
            db.close();
        super.finalize();
    }
    public synchronized void setDbHelper(DBHelper dbHelper) {
        if(null == this.dbHelper) {
            this.dbHelper = dbHelper;
            this.dbHelper.setDb(this.dbHelper.getWritableDatabase());//creates and sets the database object via getWritableDatabase()
        }
    }
}

最佳答案

如果您担心所有的数据库连接,请尝试将自己限制在一个 SqliteOpenHelper 上,并确保在其周围包裹一个同步层。

您可以扩展 application类然后调用getApplication并将您获得的对象转换到您的应用程序中。现在你可以在这个应用程序类中存储一个 SqliteOpenHelper 并构建你自己的线程安全访问数据库连接的方法。

如果您在所有 onCreate 方法中都使用 AsyncTask,并且您遇到大量选项卡的问题,这些问题也可能发生在较慢的设备、较快的用户或随着使用时间而变大的数据库上。

根据您应用的用例,您可以选择省事的方式,经历线程和锁定的所有努力和痛苦,或者您可以只发布带有多个从未产生错误的选项卡的应用,并确保捕获数据库异常并向自己发送通知(例如通过谷歌分析)以测试线程问题是否确实发生在应用程序的实际使用中。

关于android - 在创建与 SQLite 数据库交互的方法/Activity 时,我应该多注意线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3755900/

相关文章:

sql - (Perl)使用SQL::Abstract为DBI创建查询

Android SQLite DB 哪些对象必须关闭

java - AndroidManifest 虽然存在,但丢失了

ios - 为什么我的函数输出一个看起来像内存地址的随机值?

java - Web 服务手动同步后 RecyclerView 不刷新

java - 将文件写入内部存储时崩溃

android - SQLCipher - 在桌面上打开加密的数据库

java - 我将如何创建新 Activity ,我可以选择从数据库中添加新项目?

android - 相机始终将 resultCode 返回为 0

android - 从 android 2.2 中的设备远程删除数据