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.rhkb.cn/news/126907.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ: 死信队列

一、在客户端创建方式 1.创建死信交换机 2.创建类生产者队列 3.创建死信队列 其实就是一个普通的队列&#xff0c;绑定号私信交换机&#xff0c;不给ttl&#xff0c;给上匹配的路由&#xff0c;等待交换机发送消息。 二、springboot实现创建类生产者队列 1.在消费者里的…

如何选择报修管理系统?报修工单管理系统有哪些功能和优势?

报修管理系统是一种能够帮助企业快速反应设备故障和异常情况&#xff0c;并将问题及时通知到相关人员&#xff0c;并对问题进行统计和分析的系统。它能够有效提高企业的工作效率&#xff0c;并减少人员成本的支出。那么,报修工单管理系统有哪些功能和优势呢&#xff1f;下面以“…

nginx-缓存

disk cache&#xff1a;磁盘缓存数据&#xff0c;有时间延迟&#xff0c;但是非常小&#xff0c;相对于直接请求服务器返回 对于用户来说基本无感知。 memory cache&#xff1a;磁盘缓存数据&#xff0c;基本上没有时间延迟 协商缓存&#xff08;nginx自带功能&#xff0c; 不…

C++函数内联详解

本文旨在讲解C中的函数内联相关知识&#xff0c;读完这篇文章&#xff0c;希望读者们会对函数内联有更深一步的认识&#xff01; 内联函数的定义 在计算机科学中&#xff0c; 内联函数 &#xff08;有时称作 在线函数 或 编译时期展开函数 &#xff09;是一种编程语言结构&…

详解Vue中的render: h => h(App)

声明:只是记录&#xff0c;会有错误&#xff0c;谨慎阅读 我们用脚手架初始化工程的时候&#xff0c;main.js的代码如下 import Vue from vue import App from ./App.vueVue.config.productionTip falsenew Vue({// 把app组件放入容器中render: h > h(App), }).$mount(#ap…

洛谷P8814:解密 ← CSP-J 2022 复赛第2题

【题目来源】https://www.luogu.com.cn/problem/P8814https://www.acwing.com/problem/content/4732/【题目描述】 给定一个正整数 k&#xff0c;有 k 次询问&#xff0c;每次给定三个正整数 ni&#xff0c;ei&#xff0c;di&#xff0c;求两个正整数 pi&#xff0c;qi&#xf…

vue中的几种name属性

vue中的几种name属性 组件名name name选项 export default{name:xxx } // 获取组件的name属性 this.$options.namevue-devtools调试工具里显示的组件名称&#xff1b; 未配置name选项&#xff0c;就是组件的文件名&#xff1b; vue3配置name通过defineOptions()函数 de…

flink cdc多种数据源安装、配置与验证

搜索 flink cdc多种数据源安装、配置与验证 文章目录 1. 前言2. 数据源安装与配置2.1 MySQL2.1.1 安装2.1.2 CDC 配置2.2 Postgresql2.2.1 安装2.2.2 CDC 配置2.3 Oracle2.3.1 安装2.3.2 CDC 配置2.4 SQLServer2.4.1 安装2.4.2 CDC 配置3. 验证3.1 Flink版本与CDC版本的对应关系…

nlp系列(7)实体识别(Bert)pytorch

模型介绍 本项目是使用Bert模型来进行文本的实体识别。 Bert模型介绍可以查看这篇文章&#xff1a;nlp系列&#xff08;2&#xff09;文本分类&#xff08;Bert&#xff09;pytorch_bert文本分类_牧子川的博客-CSDN博客 模型结构 Bert模型的模型结构&#xff1a; 数据介绍 …

MySQL——常见问题

NULL和空值的区别 1、空值不占空间&#xff0c;NULL值占空间。当字段不为NULL时&#xff0c;也可以插入空值。 2、当使用 IS NOT NULL 或者 IS NULL 时&#xff0c;只能查出字段中没有不为NULL的或者为 NULL 的&#xff0c;不能查出空值。 3、判断NULL 用IS NULL 或者 is no…

46、TCP的“三次握手”

在上一节中&#xff0c;TCP首部常用的几个选项&#xff0c;有些选项的参数就是在通信双方在建立TCP连接的时候进行确定和协商的。所以在学习过TCP报文首部之后&#xff0c;下面我们开始学习TCP的连接建立。 TCP的一个特点是提供可靠的传输机制&#xff0c;还有一个特点就是TCP…

排序(408)

一、插入排序&#xff08;直接、折半、希尔&#xff09; 【2009统考】若数据元素序列{11,12,13,7,8,9,23,4,5}是采用下列排序方法之一得到的第二趟排序后的结果&#xff0c;则该排序算法只能是&#xff08;B&#xff09; A、冒泡排序 B、插入排序 C、选择排序 …

Elasticsearch 分布式搜索——聚合

1.聚合的种类 聚合常见的有三类&#xff1a; **桶&#xff08;Bucket&#xff09;**聚合&#xff1a;用来对文档做分组 TermAggregation&#xff1a;按照文档字段值分组&#xff0c;例如按照品牌值分组、按照国家分组Date Histogram&#xff1a;按照日期阶梯分组&#xff0c;例…

【C++】反向迭代器精讲(以list为例)

目录 二&#xff0c;全部代码 三&#xff0c;设计思路 1. 讨论 2. 关于迭代器文档一个小细节 结语 一&#xff0c;前言 如果有小伙伴还未学习普通迭代器&#xff0c;请参考这篇文章中的普通迭代器实现。 【STL】list用法&试做_底层实现_花果山~~程序猿的博客-CSDN…

Kotlin 环境下解决属性初始化问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

npm install依赖冲突解决办法

今天npm的时候发现报错&#xff0c;原来是依赖冲突了 npm后面加上这个指令就可以顺利的安装依赖了。问题主因就是不同开发用了不同版本node导致依赖版本不同&#xff0c;出现了成功冲突&#xff0c;这是段指令&#xff1b;它告诉npm忽略项目中引入的各个依赖模块之间依赖相同但…

【Linux系列】vmware虚拟机网络配置详解

非原创 原文地址[1] 首发博客地址[2] 系列文章地址[3] vmware 为我们提供了三种网络工作模式&#xff0c;它们分别是&#xff1a;Bridged&#xff08;桥接模式&#xff09;、NAT&#xff08;网络地址转换模式&#xff09;、Host-Only&#xff08;仅主机模式&#xff09;。 打开…

TCP原理(全网最详细)

一、确认应答&#xff08;可靠性机制&#xff09; TCP诞生的初衷就是可靠传输 可靠传输是TCP最核心的部分&#xff0c;TCP内部很多机制都是在保证可靠传输&#xff08;可以理解为发一条消息&#xff0c;上面显示已读未读&#xff0c;可靠传输就是发一条消息我知道对方是否收到…

前端实现展开收起的效果 (react)

需求背景&#xff1a;需要实现文本的展开收起效果&#xff0c;文本是一行一行的&#xff0c;数据格式是数组结构。 如图所示&#xff08;图片已脱敏&#xff09; 简单实现&#xff1a;使用一个变量控制展开收起效果。 展开收起逻辑部分&#xff08;react&#xff09; const […

C++——特殊类设计

C——特殊类设计 文章目录 C——特殊类设计特殊类设计一个类不能被拷贝设计一个类只能在堆上创建设计一个类只能在栈上创建设计一个类不能被继承 单例模式饿汉模式懒汉模式 特殊类 设计一个类不能被拷贝 拷贝只会放在两个场景&#xff0c;其一是拷贝构造函数&#xff0c;其二是…