Android sqlite データベースと同時書き込みに重大な問題があります。より良い説明のために、実際の例を挙げます。
私はデータベースからアイテムのリストを表示しているデスクトップ ウィジェットを持っています (そして、バックグラウンドで、定期的にリモート サーバーから新しいデータを収集し、それらでデータベースを更新する DataService を持っています)。そのため、リスト内のアイテムをクリックすると、データベース内のクリックされたアイテムを更新する (= 書き込み操作を行う) 必要があります。しかし、DataService がデータベース内の新しいデータを更新しているときに、アイテムを正確にクリックすると、もちろん次のようなエラーがログに記録されます。
android.database.sqlite.SQLiteException: error code 5: database is locked
通常、シミュレートするのは困難ですが、たとえば 10 秒ごとに実行するように DataService をスケジュールすると (デモンストレーションのためだけに)、このエラーを非常に簡単にシミュレートできます。
私の質問は、これをどのように処理するかです。同時に2つの書き込みイベントがある場合、最初にのみ実行され、2番目はエラーとしてログに記録されることをドキュメントで読みました。奇妙に聞こえますが、別のオプションが必要です。たとえば、2 番目の書き込みは最初の書き込みが完了するまで待機します。それとも他の解決策ですか?ドキュメントを読み込もうとしていますが、この項目は Google ドキュメントでカバーされていないようです...私が持っているほとんどすべての情報は、公式ページ以外で見つけました。
PS: これは、私の DBHelper クラスの短縮版です。
public class DBHelper extends SQLiteOpenHelper {
private static final String TABLE_NEWS = "News";
private static final String COL_ID = "id";
private static final String COL_TITLE = "title";
private static final String COL_ALERT = "alert";
public DBHelper(Context context) {
super(context, "MY_DB_NAME", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NEWS + "(" + COL_ID + " TEXT PRIMARY KEY," + COL_TITLE + " TEXT," + COL_ALERT + " INTEGER" + ")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NEWS);
onCreate(db);
}
public void addRecords(ArrayList<NewsItem> items) {
SQLiteDatabase db = this.getWritableDatabase();
for (int i = 0; i < items.size(); i++) {
NewsItem item = items.get(i);
ContentValues values = new ContentValues();
values.put(COL_ID, item.getId());
values.put(COL_TITLE, item.getTitle());
values.put(COL_ALERT, item.getAlertMe());
db.insert(TABLE_NEWS, null, values);
}
db.close();
}
public int updateRecord(NewsItem item) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COL_ALERT_ME, item.getAlertMe());
int updated = db.update(TABLE_NEWS, values, COL_ID + " = ?", new String[] { item.getId() });
db.close();
return updated;
}
}