Я использую адаптер синхронизации для синхронизации локальной базы данных с базой данных сервера.Запрос вызывается при изменении данных устройства для сохранения изменений на сервере.Это может быть сделано, когда устройство не имеет сетевого подключения.После подключения все запросы выполняются в случайном порядке, что может вызвать ошибку на зависимых данных.Как заставить адаптер синхронизации выполнять запросы в порядке вызова?
Вот мой адаптер синхронизации
public class SyncAdapter extends AbstractThreadedSyncAdapter {
public SyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
super(context, autoInitialize, allowParallelSyncs);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
String table = extras.getString("table");
String option = extras.getString("option");
HttpClient httpClient = new DefaultHttpClient();
String url = "http://192.168.1.136:8082/save";
HttpPost httpPost = new HttpPost();
List<NameValuePair> nameValuePair = new ArrayList<>(2);
nameValuePair.add(new BasicNameValuePair("table", table));
switch (option) {
case "SAVE":
String data = extras.getString("data");
httpPost = new HttpPost(url + "/insert");
nameValuePair.add(new BasicNameValuePair("data", data));
Log.d("SAVE", table + " " + data);
break;
case "DELETE":
Long id = extras.getLong("id");
httpPost = new HttpPost(url + "/delete");
nameValuePair.add(new BasicNameValuePair("id", id.toString()));
Log.d("DELETE", table + " " + id);
break;
}
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
try {
HttpResponse response = httpClient.execute(httpPost);
Log.d("Http Response:", response.toString());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Здесь -> syncadapter.xml
<sync-adapter android:contentAuthority="com.example.alexander.sportdiary.Sync.provider"
android:accountType="com.example.alexander.sportdiary.Sync"
android:userVisible="false"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>
Iиспользуйте простой поставщик заглушки, аутентификатор заглушки и сервис из документации.
Я использую базу данных комнаты.В местах вставки / обновления / удаления я вызываю запрос к адаптеру синхронизации с изменениями в json.
Вот методы, чтобы сделать запрос
public static void syncSave(String data, String table) {
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
//settingsBundle.putBoolean("sync_priority", true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
settingsBundle.putString("data", data);
settingsBundle.putString("table", table);
settingsBundle.putString("option", SAVE.toString());
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.requestSync(account, AUTHORITY, settingsBundle);
}
public static void syncDelete(Long id, String table) {
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
//settingsBundle.putBoolean("sync_priority", true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
settingsBundle.putLong("id", id);
settingsBundle.putString("table", table);
settingsBundle.putString("option", DELETE.toString());
ContentResolver.setIsSyncable(account, AUTHORITY, 1);
ContentResolver.requestSync(account, AUTHORITY, settingsBundle);
}
И пример вызова его
long trainingId = sportDataBase.trainingDao().insert(training);
training.setId(trainingId);
save(training);
private void save(Training training) {
AsyncTask.execute(() -> {
try {
MainActivity.syncSave(
MainActivity.getObjectMapper().writeValueAsString(
MainActivity.getConverter().convertEntityToDto(training)
), Table.TRAINING
);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
);
}
UPD : я решил использовать WorkManager вместо адаптера синхронизации.Это удовлетворяет моим требованиям: выполнять только в сети, выполнять запросы, даже если приложение выключено, выполнять запросы в порядке вызова с помощью enqueUnique со стратегией добавления.Но это все еще не ответ на вопрос.