Как сделать так, чтобы запросы к адаптеру синхронизации запускались в порядке вызова после подключения к сети - PullRequest
1 голос
/ 24 апреля 2019

Я использую адаптер синхронизации для синхронизации локальной базы данных с базой данных сервера.Запрос вызывается при изменении данных устройства для сохранения изменений на сервере.Это может быть сделано, когда устройство не имеет сетевого подключения.После подключения все запросы выполняются в случайном порядке, что может вызвать ошибку на зависимых данных.Как заставить адаптер синхронизации выполнять запросы в порядке вызова?

Вот мой адаптер синхронизации

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 со стратегией добавления.Но это все еще не ответ на вопрос.

...