import 'dart:async'; import 'package:flutter/widgets.dart'; import 'async_typeof.dart'; import 'cancel_future.dart'; class AsyncUtil { AsyncUtil._(); static CancelableFuture retryWithExponentialBackoff( FutureCallback callback, int maxRetry, Duration initialInterval, Predicate predicate) { Completer completer = Completer(); int retryCount = 0; Timer? timer; void attempt() { callback().then((value) { if (!completer.isCompleted) { completer.complete(value); } }).catchError((error) { if (retryCount < maxRetry && predicate(error)) { retryCount++; Duration nextInterval = initialInterval * (1 << (retryCount - 1)); timer = Timer(nextInterval, attempt); } else { if (!completer.isCompleted) { completer.completeError(error); } } }); } attempt(); return CancelableFuture(() { timer?.cancel(); }); } static CancelableFuture retryWhen(FutureCallback callback, int maxRetry, Duration interval, Predicate predicate) { Completer completer = Completer(); int retryCount = 0; Timer? timer; void attempt() { callback().then((value) { if (!completer.isCompleted) { completer.complete(value); } }).catchError((error) { if (retryCount < maxRetry && predicate(error)) { retryCount++; timer = Timer(interval, attempt); } else { if (!completer.isCompleted) { completer.completeError(error); } } }); } attempt(); return CancelableFuture(() { timer?.cancel(); }); } static CancelableFuture retry( FutureCallback callback, int maxRetry, Duration interval) { return retryWhen(callback, maxRetry, interval, (error) => true); } static CancelableFuture delay( FutureCallback callback, Duration interval) { Timer? timer; return CancelableFuture( () { timer?.cancel(); }, futureCompleter: (completer) { timer = Timer(interval, () { callback() .then(completer.complete) .catchError(completer.completeError); }); }, ); } ///实际delay第一次执行的时间为delay+interval static CancelableFuture interval(FutureCallback callback, Duration delay, Duration interval, int times) { Timer? timer; Timer? delayTimer; int counter = 0; Completer completer = Completer(); void tick() { if (counter < times) { callback().then((value) { if (!completer.isCompleted) { completer.complete(value); } }).catchError((error) { if (!completer.isCompleted) { completer.completeError(error); } }); counter++; } else { timer?.cancel(); } } delayTimer = Timer(delay, () { timer = Timer.periodic(interval, (Timer t) => tick()); }); return CancelableFuture(() { delayTimer?.cancel(); timer?.cancel(); }); } }