Последовательные AsyncTasks, где каждое последующее использование является результатом предыдущего - PullRequest
0 голосов
/ 03 апреля 2020

Я немного подумал об этом, и мне было интересно, какой из них может быть лучшим для выполнения sh моего запроса.

Реальный случай:

У меня много веб-вызовов, которые должны быть последовательный и где каждый вызов должен использовать результат предыдущего. Это понятие о том, что я имею в виду:

Предположим, у нас есть такая структура БД:

  • Пользователь [id, информация, созданная на стороне сервера, информация]
  • Дом [id, информация о создании на стороне сервера, информация о пользователе, информация]
  • Комната [id, информация о создании на стороне сервера, информация о доме, информация]

Предположим, что с моим приложением ( в автономном режиме) пользователь может создать свой объект пользователя, N объектов дома и N объектов комнаты для каждого дома.

Затем, когда все сделано, пользователь синхронизирует данные с сервером.

Это то, что должно быть сделано:

  1. Для каждого пользователя отправить пользователя в webapi и прочитать информацию на стороне сервера.
  2. Для каждого дома отправленного пользователя прочитать информацию на стороне сервера, отправить дом к webapi и прочитайте информацию на стороне сервера.
  3. Для каждой комнаты отправленного дома прочитайте информацию на стороне сервера, отправьте комнату в webapi и прочитайте информацию на стороне сервера.

Это можно сделать следующим образом:

  • Создать AtomicInteger, который будет подсчитывать все син c, которые должны быть готово.

Инициируйте это значение суммой пользователей, домов, комнат.

void syncDone() {
  if(totalSyncCounter.decrementAndGet() == 0){
    //sync finished, prompt user
  }
}

Создание асинхронных задач

class SendUserToDbAsyncTask extends AsyncTask<User, Void, Integer> {

    UserSavedCallback _callback;

    public SendUserToDbAsyncTask(UserSavedCallback _callback) {
        this._callback = _callback;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Integer doInBackground(User... users) {
        //save user and return the server-side value
        return serverSideInfo;
    }

    @Override
    protected void onPostExecute(Integer res) {
        super.onPostExecute(res);
        _callback.onResult(res);
    }
}

class SendHouseToDbAsyncTask extends AsyncTask<House, Void, Integer> {

    HouseSavedCallback _callback;

    public SendHouseToDbAsyncTask(HouseSavedCallback _callback) {
        this._callback = _callback;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Integer doInBackground(House... houses) {
        //save user and return the server-side value
        return serverSideInfo;
    }

    @Override
    protected void onPostExecute(Integer res) {
        super.onPostExecute(res);
        _callback.onResult(res);
    }
}

class SendRoomToDbAsyncTask extends AsyncTask<User, Void, Integer> {

    RoomSavedCallback _callback;

    public SendRoomToDbAsyncTask(RoomSavedCallback _callback) {
        this._callback = _callback;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Integer doInBackground(Room... rooms) {
        //save user and return the server-side value
        return serverSideInfo;
    }

    @Override
    protected void onPostExecute(Integer res) {
        super.onPostExecute(res);
        _callback.onResult(res);
    }
}

Logi c:

void DoStuffs() {

  mySyncCounter = [users + houses + rooms];
  for (User user : users) {
    new SendUserToDbAsyncTask(new UserSavedCallback() {
      void onResult(){
        syncDone();
        for (House house : user.houses) {
          new SendHouseToDbAsyncTask(new HouseSavedCallback() {
            void onResult(){
              syncDone();
              for (Room room : house.rooms) {
                new SendRoomToDbAsyncTask(new RoomSavedCallback() {
                  void onResult(){
                    syncDone();
                }).execute(room);
              }
          }).execute(house);
        }
    }).execute(user);
  }
}

Очевидно, это просто пример, написанный здесь на SO. Я просто хочу, чтобы вы поняли суть. Я знаю, что могу сделать один обратный вызов для всех, инициировать его вне метода, просто создать одну асинхронную задачу для всего, и т. Д. c ... но я не ищу никаких предложений по оптимизации этого конкретного кода c, Я просто хочу знать, как выполнять несколько последовательных асинхронных операций c, где каждая следующая операция использует возврат предыдущей.

Каков наилучший способ выполнения операций такого типа?

Есть ли "более чистый" способ сделать это?

Спасибо

1 Ответ

0 голосов
/ 03 апреля 2020

Если я правильно понимаю.
Вы можете использовать ExecutorService , чтобы совершать вызовы на сервер syn c, и Семафор , чтобы остановить поток, как вам нравится.
Только в любом случае вам придется использовать AsyncTask, потому что вызовы будут прерываться только с ExecutorService

...