Рекомендации по синхронизации базы данных SQL с удаленным сервером REST на Android - PullRequest
8 голосов
/ 05 марта 2012

У меня есть пользовательский Android ContentProvider, который хранит и извлекает данные из базы данных SQLite.

Предположим, что в одной из таблиц БД есть столбец _ID, столбец NAME и такой контент:

|==========|==========|
|   _ID    |   NAME   |
|==========|==========|
|    1     |    d1    |
|    2     |    d2    |
|    3     |    d3    |
|    4     |    d4    |
|==========|==========|

Эта БД SQLite синхронизируется с удаленной базой данных, и новые данные периодически выбираются по сети. Возможные операции над таблицей:

  1. Существующие строки могут быть удалены
  2. Можно добавить новые строки
  3. Столбец NAME существующих строк можно изменить

Теперь давайте предположим, что все возможные операции выполняются одновременно, и после извлечения некоторых актуальных данных с удаленного сервера новое содержимое этой таблицы должно быть установлено следующим образом:

|==========|==========|
|   _ID    |   NAME   |
|==========|==========|
|    1     |    d7    |
|    3     |    d3    |
|    4     |    d6    |
|    5     |    d5    |
|==========|==========|

Для этого может быть два разных подхода:

  1. Запросите базу данных и проверьте все существующие строки, чтобы увидеть, нужно ли их обновлять, затем добавьте все новые строки и удалите все пропущенные строки - хотя этот метод может быть немного сложным, если мы хотим обновить базу данных с нумерацией страниц подход, а не с одной сетевой выборки
  2. Удалите всю таблицу с помощью одной * SQL-команды DELETE, а затем добавьте все строки, полученные с сервера

В Android в настоящее время я реализую второй метод с пакетными операциями , чтобы максимизировать производительность:

final ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

// with this URI, the content provider deletes all rows
operations.add(ContentProviderOperation.newDelete(Users.CONTENT_URI).build());

final ContentValues values = new ContentValues();
values.put(ID_COLUMN, 1);
values.put(NAME_COLUMN, "d7");
values.put(ID_COLUMN, 3);
values.put(NAME_COLUMN, "d3");
values.put(ID_COLUMN, 4);
values.put(NAME_COLUMN, "d6");
values.put(ID_COLUMN, 5);
values.put(NAME_COLUMN, "d5");

operations.add(ContentProviderOperation.newInsert(Users.CONTENT_URI).withValues(values).build());

getApplicationContext().getContentResolver().applyBatch(MyContentProvider.AUTHORITY, operations);

Является ли это лучшим подходом, или метод 1 (или какой-либо другой метод) будет лучше с точки зрения производительности?

РЕДАКТИРОВАТЬ: например, при подходе 2 переопределенный ContentProvider#bulkInsert, который использует транзакции базы данных, может значительно ускорить операцию пакетной вставки: см. этот вопрос .

1 Ответ

1 голос
/ 05 марта 2012

Лучший вариант требует правильной реализации API - когда вы должны хранить некоторую db_version (int или метку времени последнего обновления или что-то еще).

А во время обновления сервер отвечает данными и типом операции - добавление, обновление, удаление.

...