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
访问数据所做的更改有什么建议吗
我最终采用了使用应用程序
类并存储1SQLiteOpenHelper
的方法,并尽最大努力使其保持同步。这似乎工作得很好-我把我所有的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)测试线程问题是否在应用程序的实际使用中发生。这可能是有用的。