【发布时间】:2014-01-03 03:27:18
【问题描述】:
我的应用程序中有一个 SQLite 数据库。我使用带有静态工厂的 SQLiteOpenHelper 访问它,因此一次只存在一个帮助程序实例。我不完全确定为什么这是必要的;我这样做是因为我读到如果创建了多个帮助程序,就会有一些泄漏的机会:
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper sInstance = null;
public static final String DATABASE_NAME = "score_database.db";
private static final int DATABASE_VERSION = 1;
public static final String SCORE_TABLE_NAME = "testTable";
public static final String KEY_NAME = "scorekey";
public static final String SCORE_NAME = "score";
private static final String SCORE_TABLE_CREATE =
"CREATE TABLE " + SCORE_TABLE_NAME + " (" + KEY_NAME + " INTEGER PRIMARY KEY, " + SCORE_NAME + " INTEGER);";
/**
* Constructor for DatabaseHelper class.
* @param context
*/
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* Gets the database helper instance (if an instance already exists, it will be retrieved).
* @param context The calling context
* @return The database helper instance
*/
public static DatabaseHelper getInstance(Context context) {
if(sInstance==null)
sInstance = new DatabaseHelper(context);
return sInstance;
}
/**
* Creates the necessary database structure for score storage.
* @param db The database object
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SCORE_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
我必须在不锁定 UI 线程的情况下访问它;因此,我只从 AsyncTask 内部调用 getWritableDatabase。访问完成后,我关闭 getWritableDatabase 返回的数据库。
现在,有时,我的应用程序会启动另一个相同类型的 AsyncTask,以执行另一个数据库访问,而其中一个已经在运行。我不能在多个线程中同时访问数据库,所以我有一个由所有 AsyncTask 对象共享的锁对象,该对象将数据库操作排队(这工作正常)。问题是,千载难逢,会发生以下情况:
- 应用启动 AsyncTask 锁定数据库并开始访问它。
- 用户退出应用程序(任务继续在后台运行;即使我取消它,如果我正在访问数据库,也不会停止它)。
- 用户再次打开应用程序并启动另一个 AsyncTask。因为锁是活动中的一个字段,所以这个新的 AsyncTask 获取新活动实例中的锁,并在旧任务仍在运行时访问数据库。然后,当其中一个任务关闭数据库而另一个任务尝试使用它时,就会发生错误。
这种行为是间歇性的,但这仅仅是因为满足这些条件的可能性很小。我不希望这种情况发生在用户身上。基本上,我要么需要一种方法让多个任务同时访问数据库(消除对锁的需要),要么需要一种在应用程序被销毁和重新创建时跨多个活动实例进行锁的方法。
有人有什么建议吗?
【问题讨论】:
标签: android android-asynctask android-sqlite