当前位置: 首页 > news >正文

Flutter实现CombineExecutor进行多个异步分组监听,监听第一个异步执行的开始和最后一个异步执行结束时机。

1.场景

我们在调用接口时,很多时候会同时调用多个接口,接口都是异步执行,我们很难知道调用的多个接口哪个会最后执行完成,我们有时候需要对最后一个接口执行完成的时机监听,所以基于该需求,设计了CombineExecutor,对类似的需求进行监听。

2.代码

group_key.dart

///合并执行分类
class GroupKey {///是否需要监听,不需要监听,则不会执行监听回调final bool isMonitor;GroupKey({this.isMonitor = true});
}

executor.dart

import 'group_key.dart';///执行者
///开始一个无限循环的执行进程,等待事件默认50毫秒
class Executor {final GroupKey key;///延迟时间。///进程执行的快慢,单位毫秒ms,时间越短,反应越灵敏,///但是消耗的新能越多,不能设置为0,否则会卡住进程。///默认延迟50ms。final int? delayed;bool _stop = true;Function(GroupKey key)? _stopCallback;Function(GroupKey key)? _startCallback;Executor(this.key, {this.delayed});///开始执行[Executor]///[callback]会循环调用start({Function(GroupKey key)? callback}) async {_stop = false;_startCallback = callback ?? _startCallback;while (!_stop) {_startCallback?.call(key);await Future.delayed(Duration(milliseconds: delayed ?? 50));}_stopCallback?.call(key);}///结束执行[Executor]///[callback]只会在进程结束时执行一次stop({Function(GroupKey key)? callback}) {_stop = true;_stopCallback = callback ?? _stopCallback;}///是否已启动bool isStart() {return !_stop;}@overrideint get hashCode => key.hashCode;@overridebool operator ==(Object other) =>other is! Executor ? false : key == other.key;
}

monitor.dart

import 'package:kq_flutter_widgets/utils/str_util.dart';///合并执行状态持有
class Monitor {dynamic extra;bool _isStart = false;bool _isFinish = false;bool _isError = false;Monitor({this.extra});///该方法接口开始调用时调用@Deprecated("只需要监听完成,不需要监听开始,创建即开始")onStart() {_isStart = true;}///该方法接口调用完成时调用onFinish() {_isFinish = true;}///该方法接口出错或者请求失败时调用onError() {_isError = true;}///该接口是否已开始调用@Deprecated("只需要监听完成,不需要监听开始,创建即开始")bool isStart() {return _isStart;}///该接口是否已完成调用bool isFinish() {return _isFinish;}///该接口是否调用出错bool isError() {return _isError;}///获取额外数据T? getExtra<T>() {return StrUtil.getValue(extra);}///重置,以便复用reset() {_isStart = false;_isFinish = false;_isError = false;}
}

str_util.dart

/// 字符串辅助类
class StrUtil {///类型判断static T? getValue<T>(var value) {if (value == null) {return null;} else if (T == bool) {return (value == "1" || value == "true" || value is bool) as T;} else if (T == String) {return value as T;} else if (T == int) {return int.parse(value) as T;} else if (T == double) {return double.parse(value) as T;} else {return value;}}
}

combine_executor.dart

import 'package:kq_flutter_widgets/utils/ex/kq_ex.dart';import 'core/executor.dart';
import 'core/group_key.dart';
import 'core/monitor.dart';///合并执行代码,主要用到接口调用上,
///只监测接口执行过程,不涉及接口回调参数等处理。
///以最开始执行的接口开始回调[onStart]方法,
///以最后执行完成的接口回调[onFinish]方法。
///当第一个回调开始了,并已回调完成了,表示整个接口执行完毕,
///当第一个接口执行完毕后,还没开始执行第二个接口,则即使他们有共同的[GroupKey],
///他们也不能在一个处理周期中处理,我们把一个同一个[GroupKey]下执行的[onStart]和[onFinish],
///表示一个处理周期。
class CombineExecutor {///执行的对象保存final Map<GroupKey, List<Monitor>> _combines = {};///Executor 保存final List<Executor> _executors = [];final Function(GroupKey key)? onStart;final Function(GroupKey key)? onFinish;CombineExecutor({this.onStart, this.onFinish});_executor(GroupKey key) {Executor executor = Executor(key);if (!_executors.contains(executor)) {_executors.add(executor);onStart?.call(key);executor.start(callback: (key) {List<Monitor> combines = _getCombines(key);bool flag = true;for (Monitor combineMonitor in combines) {if (!combineMonitor.isFinish() && !combineMonitor.isError()) {flag = false;break;}}//表示最后一个都已执行完成if (flag) {executor.stop(callback: (key) {onFinish?.call(key);_clearCombine(key);_executors.remove(executor);});}});}}///停止,在退出界面时调用stop() {for (Executor executor in _executors) {executor.stop();}_executors.clear();_clearAllCombine();}///获取合并执行观察者,///设置到请求逻辑中。Monitor getCombine(GroupKey key) {Monitor combineMonitor = Monitor();_addCombine(key, combineMonitor);_executor(key);return combineMonitor;}///新增一个CombineMonitor_addCombine(GroupKey key, Monitor combine) {if (key.isMonitor) {if (_combines.containsKey(key)) {List<Monitor>? combines = _combines[key];combines ??= [];if (!combines.contains(combine)) {combines.add(combine);}} else {_combines.putIfAbsent(key, () => [combine]);}}}List<Monitor> _getCombines(GroupKey key) {if (_isEmptyCombine(key)) {return [];} else {return _combines[key]!;}}///CombineMonitor是否为空_isEmptyCombine(GroupKey key) {return !_combines.containsKey(key) || _combines[key].isNullOrEmpty;}_clearCombine(GroupKey key) {_combines.remove(key);}///清除全部的CombineMonitor_clearAllCombine() {_combines.clear();}
}///测试
class Test {test() {///创建一个GroupKey,改key可用于一组需要调用的接口上GroupKey groupKey = GroupKey();///创建对象CombineExecutor executor = CombineExecutor(onStart: (key) {///print("执行了onStart");},onFinish: (key) {if (key == groupKey) {///print("执行了onFinish");}},);///获取CombineMonitor 传入到接口调用中Monitor monitor = executor.getCombine(groupKey);///模拟异步对Monitor进行操作Future.delayed(const Duration(seconds: 2), () {monitor.onFinish();});///退出界面executor.stop();}
}

3.使用

http://www.lryc.cn/news/160988.html

相关文章:

  • 2023 年最新Java 毕业设计选题题目参考,500道 Java 毕业设计题目,值得收藏
  • Mac电脑其他文件占用超过一大半的内存如何清理?
  • geopandas 笔记: datasets 数据集
  • 长胜证券:三大拐点共振 看好智能驾驶新一轮行情
  • AIGC专栏5——EasyPhoto AI写真照片生成器 sd-webui插件介绍、安装与使用
  • 【Python程序设计】 工厂模式【07/8】
  • PHP8的多维数组-PHP8知识详解
  • 【【STM32--28--IO引脚的复用功能】】
  • CodeJock Active-X / COM v22.1.0 Crack
  • mac通过docker搭建elasticsearch:8.9.2以及kibana:8.9.2
  • python实现排列组合代码
  • 盲盒小程序开发方案
  • Mysql锁
  • Kubernetes(k8s)安装NFS动态供给存储类并安装KubeSphere
  • 机器学习笔记 - 【机器学习案例】基于KerasCV的预训练模型自定义多头+多标签预测
  • Linux Debian常用70条经典运维命令和使用案例
  • 【涵子来信】——步入中学,日积跬步,以致千里
  • 【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
  • 数据库相关基础知识
  • LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)
  • C++算法 —— 分治(2)归并
  • Hadoop YARN HA 集群安装部署详细图文教程
  • BBS+商城项目的数据库表设计
  • 如何使用Savitzky-Golay滤波器进行轨迹平滑
  • Nomad系列-Nomad网络模式
  • OpenCV项目开发实战--实现面部情绪识别对情绪进行识别和分类及详细讲解及完整代码实现
  • Validate表单组件的封装
  • 企业架构LNMP学习笔记32
  • 基于Jetty9的Geoserver配置https证书
  • 企业互联网暴露面未知资产梳理