如果我没记错的话,有几种Android API(在甜甜圈之后和蜂窝之前),其中Google启用了AsyncTasks并行运行,旨在更快地执行。然后,许多开发人员在使用多个AsyncTasks到达同一数据库时犯了错误,并且由于默认情况下Android 3.0 AsyncTasks串行运行。
我现在在使用SQLite在Android 2.3.4设备上测试我的应用程序时遇到了这个问题
首先,我从服务器获取类别,然后打开数据库,将其插入以关闭数据库。
其次,我从服务器获取子类别,打开数据库,将其插入数据库,关闭数据库
第三,我从服务器获取用户项目,打开数据库,插入项目,然后关闭数据库
我小心翼翼地确保一个接一个地启动,但是在每8-10次迭代中,某个位置在某个任务打开db的那一刻,某个地方的速度变慢并与另一个过程重叠,另一个任务紧随其后关闭,然后第一个任务关闭任务开始尝试写入已关闭的数据库。
我该怎么办?我想要干净,可靠的分离,顺序执行,并且我不想从以前的asynctask的onPostExecute开始asynctask,因为这三个命令不会总是连续运行
昨天我读了一篇文章,您无法在android 2.x上执行此操作
我是否应该在所有操作之前尝试打开数据库和DBHelper,然后再关闭数据库?
编辑:通常我在这里(在Begin事务处)收到错误:(错误表明数据库已关闭)
@Override
protected Void doInBackground(Void... arg0) {
// dbTools.close();
try {
if (database == null) {
database = dbTools.getWritableDatabase();
}
} catch (Exception e) {
e.printStackTrace();
}
ContentValues values = new ContentValues();
database.beginTransaction();
try {
// Iterating all UserItem objects from the LinkedHashSet and getting their info
for (UserItem userItem : userItems) {
// Inserting values for the database to insert in a new record
values.put(C.DBColumns.ITEM_ID, userItem.getItemId());
values.put(C.DBColumns.ITEM_NAME, userItem.getItemName());
// database.insertWithOnConflict(C.DBTables.ITEMS, null, values, SQLiteDatabase.CONFLICT_REPLACE);
database.insert(C.DBTables.ITEMS, null, values);
} // End of For loop
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
// Closing all cursors, databases and database helpers properly because not closing them can spring lots of trouble.
if (database != null && database.isOpen()) {
try {
database.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
} // End of doInBackground
这是我的DBTOOLS类别:
public class DBTools extends SQLiteOpenHelper {
// Its a good practice for DBTools to be a singleton. Do not instantiate it with "new DBTools(context)" but with
// DBTools.getInstance(context) instead
private static DBTools sInstance;
public static DBTools getInstance(Context context) {
if (sInstance == null) {
sInstance = new DBTools(context);
}
return sInstance;
}
public DBTools(Context context) {
super(context, C.Preferences.LOCAL_SQLITE_DATABASE_NAME, null, 1);
}
public void onCreate(SQLiteDatabase database) {
database.execSQL(SQLQueries.tableCategoriesCreate);
database.execSQL(SQLQueries.tableSubcategoriesCreate);
database.execSQL(SQLQueries.tableItemsCreate);
}
public void onOpen(SQLiteDatabase database) {
database.execSQL(SQLQueries.tableCategoriesCreate);
database.execSQL(SQLQueries.tableSubcategoriesCreate);
database.execSQL(SQLQueries.tableItemsCreate);
}
public void onUpgrade(SQLiteDatabase database, int version_old, int current_version) {
database.execSQL(SQLQueries.tableCategoriesDrop);
database.execSQL(SQLQueries.tableSubcategoriesDrop);
database.execSQL(SQLQueries.tableItemsDrop);
onCreate(database);
}
} // End of Class
由于您无法通过onPostExecute进行调用,因此我想您有两种选择,一种是将打开关闭调用移至活动或服务的开始和结束。
第二种方法是在DB和DBHelper中设置一个参考计数器,在其中跟踪打开被调用的次数,然后在调用关闭时减少该计数。这样,仅当计数为0时才可以执行关闭操作。采用这种方法时要记住的一件事是,您可能应该有一个方法,当您确定其他连接已完成时,该方法将强制数据库关闭。这不是必须的,但是可以确保故障发生时关闭数据库。
编辑:您必须使DBTools成为单例才能正常工作,但这不是等效的。这是一个简单的例子。
public class DBTools {
private static DBTools instance;
private static int openCount;
public DBTools getInstance() {
if (instance == null) {
instance = new DBTools();
}
return instance;
}
private DBTools() {
openCount = 0;
}
public void open() {
openCount++;
//Do open
}
public close() {
openCount--;
if (openCount == 0) {
//Do close
}
public void forceDBClose() {
//Do close
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句