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

Android 在创建与SQLite数据库交互的方法/活动时,我在线程安全方面应该多小心?,android,sqlite,Android,Sqlite,我正在创建一个应用程序,它允许从选项卡activity启动许多不同的活动(最多25个)。大多数活动都需要来自sqlite数据库的数据,因此当运行onCreate时,AsyncTask会创建一个SQLiteOpenHelper对象(它将打开一个可读写的数据库),运行一个查询,检索数据,然后关闭所有内容 我只是在测试是否可以破坏某些东西,所以我将每个活动添加到TabActivity的TabHost。然后我开始尽可能快地捣碎每个标签 我很快注意到,我开始在LogCat中看到:是由以下原因引起的:and

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

我只是在测试是否可以破坏某些东西,所以我将每个
活动
添加到
TabActivity的
TabHost
。然后我开始尽可能快地捣碎每个标签

我很快注意到,我开始在LogCat中看到:
是由以下原因引起的:android.database.sqlite.SQLiteException:database is locked:BEGIN EXCLUSIVE和应用程序继续死亡

通常,
TabHost
只有大约4-6个选项卡(我可以限制用户)。我还不能用少量的标签来破坏任何东西,但是我仍然担心我访问数据库的方式可能不好

如何防止SQLiteDatabase对象导致锁定

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

您对我从
SQLiteDatabase
访问数据所做的更改有什么建议吗

我最终采用了使用
应用程序
类并存储1
SQLiteOpenHelper
的方法,并尽最大努力使其保持同步。这似乎工作得很好-我把我所有的25个活动都放在
TabHost
中,并在上面捣乱,没有任何错误

我正在调用
((SQLiteDbApplication)getApplication()).setDbHelper(新的DBHelper(this,Constants.DB_NAME,null,Constants.DB_VERSION_code))onCreate()
中的code>方法(如下所示)

对这种方法或我使用这个
应用程序所做的更改有什么进一步的建议吗

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()
        }
    }
}

所有活动回调都发生在主线程上,因此在您描述的场景中,无论有多少活动或选项卡,都没有多线程

ContentProvider不提供任何锁定。事实上,它可以在您还没有多线程的地方引入多线程,因为它允许其他进程调用您自己的进程,而当这种情况发生时,调用将从进程中的单独线程(而不是在主UI线程上)调度


当然,如果您创建自己的线程,那么您也将有多线程。如果您担心所有数据库连接,请尝试将自己限制为一个SqliteOpenHelper,并确保在其周围包装一个同步层

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

如果在所有onCreate方法中都使用AsyncTask,并且在很多选项卡上遇到问题,那么这些问题也可能发生在速度较慢的设备、速度较快的用户或随着使用时间而增长的数据库上

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

这可能是有用的。