我的应用程序中有一个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对象共享的锁对象,这些对象将数据库操作排队(这很好)。问题是,一旦在蓝色的月亮,会发生以下情况:
这种行为是间歇性的,但这只是因为这些条件得到满足的可能性很小。我不希望这种情况发生在用户身上。基本上,我要么需要一种方法让多个任务同时访问数据库(不需要锁定),或者在应用程序被销毁和重新创建时让锁定进入多个活动实例。
有人有什么建议吗?
答案 0 :(得分:2)
根据经验,我会尽可能地依赖Android操作系统。也就是说,为什么不使用Content Provider进行数据库操作?它有点为您处理多线程/事务/锁定DB。 作为替代方案(并且此解决方案闻起来不是很好),您可以在SharedPreferences中备份您的锁定字段,因为它存储在文件中,它会在应用程序的死亡和重生时保留它,只需将其恢复到创建状态。
答案 1 :(得分:1)
SQLiteOpenHelper
进行建模,以便缓存SQLite连接以便重用。在这种情况下,没有必要手动关闭连接,虽然帮助程序将在下次访问时自动重新打开新连接,因此如果访问保持序列化,它仍然可以工作。
根据我的经验,SQLite事务是由框架序列化的,所以如果你使用上面的模型,那么你不需要自己序列化它们。
另外,为了评论您的序列化方案,您应该将共享锁保持在与AsyncTask
相同的级别(最好使用SQLiteOpenHelper
对象本身作为锁)。您也可以在executeOnExecutor()
方法中指定一个串行执行器,这是默认的前甜甜圈,并且再次被恢复为默认的后蜂窝。