Параллельная запись в базу данных Android (из нескольких служб)?

У меня серьезная проблема с базой данных android sqlite и одновременной записью. Для лучшего пояснения приведу пример из жизни:

У меня есть виджет на рабочем столе, где я показываю список элементов из моей базы данных (а в фоновом режиме у меня есть DataService, который через равные промежутки времени собирает свежие данные с моего удаленного сервера и обновить мою базу данных с их помощью). Итак, когда я нажимаю на какой-либо элемент в списке, мне нужно обновить выбранный элемент (= выполнить операцию записи) в базе данных. НО, когда я нажимаю на элемент точно в тот момент, когда 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;
    }
}
12
задан PhilLab 4 July 2017 в 08:40
поделиться