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

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

我只是在测试乱搞,看看我是否能破坏某些东西,所以我将每个Activity添加到TabActivity的TabHost中.然后我开始尽快将每个标签混合在一起.

我注意到很快我开始在LogCat中看到:引起:android.database.sqlite.SQLiteException:数据库被锁定:BEGIN EXCLUSIVE;而应用程序继续死亡.

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

如何防止我的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()
        }
    }
}

解决方法

如果您担心所有数据库连接,请尝试将自己限制为一个SqliteOpenHelper,并确保围绕它包装同步层.

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

如果您在所有onCreate方法中使用AsyncTask并且遇到许多选项卡问题,那么这些问题也可能发生在速度较慢的设备,更快的用户或在使用时变大的数据库中.

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

相关文章

Android 如何解决dialog弹出时无法捕捉Activity的back事件 在...
Android实现自定义带文字和图片的Button 在Android开发中经常...
Android 关于长按back键退出应用程序的实现最近在做一个Andr...
android自带的时间选择器只能精确到分,但是对于某些应用要求...