在创建与SQLite数据库交互的方法/活动时,我应该多么小心使用线程安全性?

jam*_*mes 7 sqlite android

我正在创建一个应用程序,允许Activities从a TabActivity(最多~25)启动许多不同的应用程序.大多数活动都需要来自sqlite数据库的数据,因此在onCreate运行时,AsyncTask会创建一个SQLiteOpenHelper对象(它将打开一个可读/可写的数据库),运行查询,检索数据,然后关闭所有内容.

我只是在考验插科打诨,看看我能打破一些东西,所以我说每ActivityTabActivity's TabHost.然后我开始尽快将每个标签混合.

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

通常情况下,只有大约4-6个标签(我可以只限制用户)TabHost.我无法通过少量标签来破坏任何东西,但我仍然担心我可能会以糟糕的方式访问数据库.

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

如果我创建一个ContentProvider遗嘱,消除数据库锁定的可能性?

您是否有任何关于我可以为从中访问数据所做的更改的建议SQLiteDatabase

我最终采用了使用Application该类并存储1 的方法,SQLiteOpenHelper并尽力使其保持同步.这似乎工作得很好 - 我把我所有的25个活动都放进TabHost去并且没有任何错误.

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

对此方法或使用此类所做的更改的任何进一步建议Application

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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jan*_*usz 2

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

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

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

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