У меня серьезная проблема с базой данных android sqlite и одновременной записью. Для лучшего объяснения, я приведу вам пример реальной жизни:Одновременная запись в базу данных Android (из нескольких служб)?
У меня виджет рабочего стола, где я показываю список предметов из моей базы данных (а на заднем плане у меня есть DataService, который через регулярные промежутки времени собирает свежие данные с моего удаленного сервера и обновить мою базу данных). Итак - когда я нажимаю на какой-либо элемент в списке, мне нужно обновить элемент clicked (= do write operation) в базе данных. НО когда я нажимаю на деталь точно в момент, когда DataService обновляет свежие данные в моей базе данных, это, конечно, регистрирует ошибку, как это:
android.database.sqlite.SQLiteException: error code 5: database is locked
Обычно его трудно имитировать, но если и график DataService баллотироваться пример каждые 10 секунд (только для демонстрации), вы можете очень легко имитировать эту ошибку.
И мой вопрос в том, как с этим справиться? Я прочитал в документах, что если в одно время будут два события записи, будет выполнено только первое, второе будет зарегистрировано как ошибка. Звучит странно, должны быть и другие варианты, например, вторая запись будет ждать до первого написания. Или, может быть, другое решение? Попытка читать документы, но кажется, что этот элемент не очень хорошо освещен в документах 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;
}
}
Возможно, вы открываете и закрываете несколько соединений с базами данных в разных потоках. Это не очень хорошо. Вы должны открыть одно соединение с базой данных. – Sajmon
thats true, я делаю что-то вроде этого в моих сервисах: DBHelper dbHelper = new DBHelper (this); и т. д. ... но как создать только один экземпляр - что произойдет, если мой процесс будет уничтожен? PS: пожалуйста, нажмите «Ответ на ваш запрос», - я могу написать вам прямо, (если кто-то еще комментирует здесь, это будет многопользовательский разговор) – qkx
обычно добавить синхронизированный для каждого метода, связан с db open/close. – Richard