API задачи служб Google Play: continueWith vs continueWithTask

Это задание.

в чем разница между task.continueWith() и task.continueWithTask(), вы можете привести пример для каждого из них?

3 ответов


основная разница между continueWith и continueWithTask является одним из общих типов продолжение вы переходите к нему.

вы можете думать о продолжении как о чем-то, что преобразует некоторый тип ввода в некоторый тип вывода. Если вы определяете Continuation<IN, OUT>, где IN - Это тип ввода, переданный его then способ через Task<IN> и OUT - это тип, который возвращает метод.

при вызове continueWith, передать Continuation<IN, OUT> и then ожидается, что метод вычислит и вернет OUT значение дано Task<IN> значение в качестве входных данных. Вы можете сделать это, если у вас нет никакой блокирующей работы для преобразования, такой как уменьшение целого массива до суммы его элементов или подсчет количества слов в строке.

при вызове continueWithTask, передать Continuation<IN, Task<OUT>> и then ожидается, что метод вернет Task<OUT> что в конечном итоге создает OUT значение, учитывая IN значение в качестве входных данных. Вы можете выбрать это, если сможете делегировать работу преобразования существующей многоразовой задаче.

практически говоря, вы не обязаны выбирать тот или иной для выполнения своей работы. Это вопрос стиля, или если у вас есть хороший Task готов делегировать свой разговор, а не Continuation. Обычно вы используете продолжения, только если у вас есть конвейер преобразований в цепочку вместе.

ссылки javadoc здесь показывают некоторые примеры продолжений. Также, чтобы узнать больше, вы можете прочитать о них в часть третья из моей серии блогов. Справедливости ради,continueWithTask - единственная часть API задач, которую я непосредственно не обсуждаю нигде в этой серии, в основном потому, что концептуально она не сильно отличается от continueWith.


чтобы добавить к тому, что сказал Дуг, я бы сказал так:

continueWith обернет результат then метод Task. continueWithTask не будет; он ожидает then метод, чтобы возвратить Task, и таким образом избегает двойной упаковки задачи внутри задачи.

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


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

tl; dr

когда использовать какой метод:

  1. использовать continueWith Если вы хотите использовать результат предыдущей задачи и вернуть новый результат в пределах вашего продолжения then метод. И нужно передать его какому-нибудь другому продолжению или использовать потом в слушателях. возвращаемое значение continueWith-это задача, которая просто обертывает ваше возвращаемое значение then метод.

  2. использовать continueWithTask если вы хотите использовать результат предыдущей задачи, и несколько использовать его в новая задача, что вы создаете в рамках вашего продолжения then метод. возвращаемое значение continueWithTask-это задача, которую вы создаете внутри then и имеет собственный общий результат.


Do не верните задачу в своем продолжении и используйте ее с continueWith. Он может компилироваться и выполняться годами без предупреждения, но также и без выполнения своей работы.

если вы напрямую добавляете слушателя после continueWith этот слушатель даст вам задачу, которая только обертывает результат вашего then вернуться значение. Если это возвращаемое значение является задачей себя, не ожидайте, что это будет казнен(!!!).


долгая история!

у меня была такая цепочка звонков:

private Task<SomeResult> getTask() {

    PreloadingTask.create().continueWith(additionalTask()).addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            source.setResult(someResult);
        } else {
            source.setException(new Exception());
        }
    });
    return source.getTask();
}

так как вы можете видеть,additionalTask() должен вернуться какой-то Continuation<IN, OUT>, который реализует метод, тогда как

@Override 
public OUT then(Task<IN> task){ ... }};

в моем случае мне не нужно, чтобы проверить OUT, потому что я просто хотел сделать некоторые дополнительные вычисления после PreloadingTask было сделано и вперед, это результат для моего additionalTask() продолжение.

я хотел выполнить задачу от additionalTask(), а потом onCompleteListener должен был быть вызван.

private Continuation<PreviousResult, Task<Void>> additionalTask() {
        return task -> {
            PreviousResult r = task.getResult();
            simpleResultModification(r);
            return new AdditionalTask(r);
            );
        };
    }

что случилось? The onCompleteListener был вызван напрямую, потому что мой then метод был выполнен и вернул его результат, который был экземпляром AdditionalTask. Это обвели в другое задание и передал для onCompleteListener в результате.

и мой AdditionalTask никогда не выполняется.

вот почему вы должны использовать continueWithTask, если вы возвращаете задачу, в то время.