Browse Source

[new]增加重试工具类

zk 1 year ago
parent
commit
2fa97659d3

+ 5 - 1
lib/data/api/atmob_api.dart

@@ -22,7 +22,7 @@ import 'package:electronic_assistant/data/api/response/home_info_response.dart';
 import 'package:electronic_assistant/data/api/response/login_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_check_electric_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_info_response.dart';
-import 'package:electronic_assistant/data/bean/talk_info.dart';
+import 'package:electronic_assistant/data/api/response/tasks_running_response.dart';
 import 'package:electronic_assistant/data/api/response/talk_original_response.dart';
 import 'package:electronic_assistant/data/bean/talks.dart';
 import 'package:electronic_assistant/data/consts/constants.dart';
@@ -95,6 +95,10 @@ abstract class AtmobApi {
   /// 录音完成,创建谈话记录
   @POST("/project/secretary/v1/talk/create")
   Future<BaseResponse<TalkBean>> talkCreate(@Body() TalkCreateRequest request);
+
+  @POST("/project/secretary/v1/talk/tasks/running")
+  Future<BaseResponse<TasksRunningResponse>> tasksRunning(
+      @Body() AppBaseRequest request);
 }
 
 final atmobApi = AtmobApi(defaultDio, baseUrl: Constants.baseUrl);

+ 14 - 0
lib/data/api/response/tasks_running_response.dart

@@ -0,0 +1,14 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'tasks_running_response.g.dart';
+
+@JsonSerializable()
+class TasksRunningResponse {
+  @JsonKey(name: 'taskIds')
+  List<String>? taskIds;
+
+  TasksRunningResponse({this.taskIds});
+
+  factory TasksRunningResponse.fromJson(Map<String, dynamic> json) =>
+      _$TasksRunningResponseFromJson(json);
+}

+ 21 - 0
lib/data/repositories/task_repository.dart

@@ -0,0 +1,21 @@
+import 'package:electronic_assistant/base/app_base_request.dart';
+import 'package:electronic_assistant/data/api/atmob_api.dart';
+
+import '../../utils/http_handler.dart';
+import '../api/response/tasks_running_response.dart';
+
+class TaskRepository {
+  TaskRepository._();
+
+  void startUnfinishedTask() {
+    tasksRunning();
+  }
+
+  Future<TasksRunningResponse> tasksRunning() {
+    return atmobApi
+        .tasksRunning(AppBaseRequest())
+        .then(HttpHandler.handle(true));
+  }
+}
+
+final taskRepository = TaskRepository._();

+ 1 - 1
lib/main.dart

@@ -13,7 +13,7 @@ import 'package:pull_to_refresh/pull_to_refresh.dart';
 void main() async {
   WidgetsFlutterBinding.ensureInitialized();
 
-  //全局配置smart
+  //全局配置smartDialog
   smartConfig();
   //获取包信息
   appInfoUtil.init();

+ 3 - 2
lib/router/app_pages.dart

@@ -85,7 +85,8 @@ final generalPages = [
   GetPage(name: RoutePath.taskSearch, page: () => const TaskSearchPage()),
   GetPage(name: RoutePath.record, page: () => const RecordPage()),
   GetPage(name: RoutePath.talkDetail, page: () => const TalkPage()),
-  GetPage(name: RoutePath.record, page: () =>  const RecordPage()),
-  GetPage(name: RoutePath.talkDetail, page: () => TalkPage()),
+  GetPage(name: RoutePath.record, page: () => const RecordPage()),
+  GetPage(name: RoutePath.talkDetail, page: () => const TalkPage()),
   GetPage(name: RoutePath.store, page: () => const StorePage()),
+  GetPage(name: RoutePath.talkDetail, page: () => const TalkPage()),
 ];

+ 9 - 0
lib/utils/async_typeof.dart

@@ -0,0 +1,9 @@
+import 'dart:async';
+
+typedef FutureCallback<T> = Future<T> Function();
+
+typedef Cancelable<T> = void Function();
+
+typedef FutureCompleter<T> = void Function(Completer<T> completer);
+
+typedef Predicate<T> = bool Function(T? value);

+ 131 - 0
lib/utils/async_util.dart

@@ -0,0 +1,131 @@
+import 'dart:async';
+
+import 'package:flutter/widgets.dart';
+
+import 'async_typeof.dart';
+import 'cancel_future.dart';
+
+class AsyncUtil {
+  AsyncUtil._();
+
+  static CancelableFuture<T> retryWithExponentialBackoff<T>(
+      FutureCallback<T> callback,
+      int maxRetry,
+      Duration initialInterval,
+      Predicate<dynamic> predicate) {
+    Completer<T> completer = Completer<T>();
+    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<T>(() {
+      timer?.cancel();
+    });
+  }
+
+  static CancelableFuture<T> retryWhen<T>(FutureCallback<T> callback,
+      int maxRetry, Duration interval, Predicate<dynamic> predicate) {
+    Completer<T> completer = Completer<T>();
+    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<T>(() {
+      timer?.cancel();
+    });
+  }
+
+  static CancelableFuture<T> retry<T>(
+      FutureCallback<T> callback, int maxRetry, Duration interval) {
+    return retryWhen(callback, maxRetry, interval, (error) => true);
+  }
+
+  static CancelableFuture<T> delay<T>(
+      FutureCallback<T> callback, Duration interval) {
+    Timer? timer;
+    return CancelableFuture<T>(
+      () {
+        timer?.cancel();
+      },
+      futureCompleter: (completer) {
+        timer = Timer(interval, () {
+          callback()
+              .then(completer.complete)
+              .catchError(completer.completeError);
+        });
+      },
+    );
+  }
+
+  ///实际delay第一次执行的时间为delay+interval
+  static CancelableFuture<T> interval<T>(FutureCallback<T> callback,
+      Duration delay, Duration interval, int times) {
+    Timer? timer;
+    Timer? delayTimer;
+    int counter = 0;
+    Completer<T> completer = Completer<T>();
+
+    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<T>(() {
+      delayTimer?.cancel();
+      timer?.cancel();
+    });
+  }
+}

+ 45 - 0
lib/utils/cancel_future.dart

@@ -0,0 +1,45 @@
+import 'dart:async';
+import 'async_typeof.dart';
+
+class CancelableFuture<T> implements Future<T> {
+  final Completer<T> _completer = Completer<T>();
+
+  Cancelable? cancelable;
+
+  CancelableFuture(this.cancelable, {FutureCompleter? futureCompleter}) {
+    futureCompleter?.call(_completer);
+  }
+
+  void cancel() {
+    cancelable?.call();
+  }
+
+  @override
+  Stream<T> asStream() => _completer.future.asStream();
+
+  @override
+  Future<T> catchError(Function onError, {bool Function(Object error)? test}) =>
+      _completer.future.catchError(onError, test: test);
+
+  @override
+  Future<R> then<R>(FutureOr<R> Function(T value) onValue,
+          {Function? onError}) =>
+      _completer.future.then(onValue, onError: onError);
+
+  @override
+  Future<T> timeout(Duration timeLimit, {FutureOr<T> Function()? onTimeout}) =>
+      _completer.future.timeout(timeLimit, onTimeout: onTimeout);
+
+  @override
+  Future<T> whenComplete(FutureOr<void> Function() action) =>
+      _completer.future.whenComplete(action);
+}
+
+extension CancelableFutureExtension<T> on Future<T> {
+  CancelableFuture<T> asCancelable(
+    Cancelable cancelable, {
+    FutureCompleter? futureCompleter,
+  }) {
+    return CancelableFuture(cancelable, futureCompleter: futureCompleter);
+  }
+}