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.使用

相关文章:
Flutter实现CombineExecutor进行多个异步分组监听,监听第一个异步执行的开始和最后一个异步执行结束时机。
1.场景 我们在调用接口时,很多时候会同时调用多个接口,接口都是异步执行,我们很难知道调用的多个接口哪个会最后执行完成,我们有时候需要对最后一个接口执行完成的时机监听,所以基于该需求,设计了CombineE…...
2023 年最新Java 毕业设计选题题目参考,500道 Java 毕业设计题目,值得收藏
大家好,我是程序员徐师兄,最近有很多同学咨询,说毕业设计了,不知道选怎么题目好,有哪些是想需要注意的。 确实毕设选题实际上对很多同学来说一个大坑, 每年挖坑给自己跳的人太多太多,选题选得好…...
Mac电脑其他文件占用超过一大半的内存如何清理?
mac的存储空间时不时会提示内存已满,查看内存占用比例最大的居然是「其他文件」,「其他文件」是Mac无法识别的格式文件或应用插件扩展等等...如果你想要给Mac做一次彻底的磁盘空间清理,首当其冲可先对「其他文件」下手,那么我们该…...
geopandas 笔记: datasets 数据集
geopandas 自带的几个数据集 1 世界各个国家 import geopandas as gpd import pandas as pdpd.set_option(display.max_rows,None) gpd.read_file(gpd.datasets.get_path(naturalearth_lowres)) pop_est人口数量continent国家所在的大陆name国家的名称iso_a3国家的三个字母的…...
长胜证券:三大拐点共振 看好智能驾驶新一轮行情
摘要 【长胜证券:三大拐点共振 看好智能驾驭新一轮行情】长胜证券研报指出,全球共振,国内智驾商场正迎来三大拐点:1)技能上,“BEV Transformer数据闭环”新架构2023年开端上车,使得不依靠高精地…...
AIGC专栏5——EasyPhoto AI写真照片生成器 sd-webui插件介绍、安装与使用
AIGC专栏5——EasyPhoto AI写真照片生成器 插件安装与使用 学习前言源码下载地址技术原理储备(SD/Control/Lora)StableDiffusionControlNetLora EasyPhoto插件简介EasyPhoto插件安装安装方式一:Webui界面安装 (需要良好的网络&…...
【Python程序设计】 工厂模式【07/8】
一、说明 我们探索数据工程中使用的设计模式 - 软件设计中常见问题的可重用解决方案。 以下文章是有关 Python 数据工程系列文章的一部分,旨在帮助数据工程师、数据科学家、数据分析师、机器学习工程师或其他刚接触 Python 的人掌握基础知识。 迄今为止,…...
PHP8的多维数组-PHP8知识详解
今天分享的是php8的数组中的多维数组,主要内容有:多维数组的概念、创建和输出二维数组、创建和输出三维数组。 1、多维数组的概念 多维数组是包含一个或多个数组的数组。在多维数组中,主数组中的每一个元素也可以是一个数组,子数…...
【【STM32--28--IO引脚的复用功能】】
STM32–28–IO引脚的复用功能 STM32的IO复用功能 何为复用? 我们先了解一下何为通用 IO端口的输入或输出是由GPIO外设控制,我们称之为通用 复用: IO端口的输入或者是输出是由其他非GPIO外设控制就像经常说的USART 由 DR寄存器进行输出 STM32的IO复用功…...
CodeJock Active-X / COM v22.1.0 Crack
CodeJock Active-X / COM v22.1.0--这个支持 Unicode 啦, Unicode Unicode 创建专业应用程序,其中包含一整套高度可定制的用户界面组件,包括 Visual Studio 风格的对接窗格和 Office 风格的功能区、工具栏和菜单,为您的应用程序…...
mac通过docker搭建elasticsearch:8.9.2以及kibana:8.9.2
1.elasticsearch.yml配置修改: cluster.name: "docker-cluster" network.host: 0.0.0.0 http.port: 9200 #discovery.seed_hosts: ["172.17.0.2"]#----------------------- BEGIN SECURITY AUTO CONFIGURATION ----------------------- # # T…...
python实现排列组合代码
def combination(n, c, com1, limit0, per[]):for pos in range(limit, n):t per [pos]if len(set(t)) len(t):if len(t) c:yield [pos, ]else:for result in combination(n, c, com, com * pos, per [pos, ]):yield [pos, ] resultprint("排列:") …...
盲盒小程序开发方案
盲盒游戏作为一种富有趣味性和收藏价的虚拟盲盒产品,近年来在游戏市场中备受关注。本文将深入探讨盲盒游戏的开发方案,从市场趋势分析、用户体验设计、商业模式选择等多个维度,为开发者提供业且有深度的思考,以帮助他们在盲盒游戏…...
Mysql锁
文章目录 1. 概述2. 分类3. 全局锁4. 表级锁5. 行级锁 1. 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并…...
Kubernetes(k8s)安装NFS动态供给存储类并安装KubeSphere
Kubernetes安装NFS动态供给存储类并安装KubeSphere KubeSphere介绍环境准备KubeSphereNFS动态供给 安装NFS动态供给搭建NFS下载动态供给驱动修改驱动文件安装动态供给 安装KubeSphere下载KubeSphere的yaml资源清单文件安装KubeSphere 使用KubeSphere部署应用创建项目部署MySQL …...
机器学习笔记 - 【机器学习案例】基于KerasCV的预训练模型自定义多头+多标签预测
一、KerasCV KerasCV 是一个模块化计算机视觉组件库,可与 TensorFlow、JAX 或 PyTorch 原生配合使用。这些模型、层、指标、回调等基于Keras Core构建,可以在任何框架中进行训练和序列化,并在另一个框架中重复使用,而无需进行昂贵的迁 KerasCV 可以理解为 Keras API 的水平…...
Linux Debian常用70条经典运维命令和使用案例
一、前言 今天分享一些Linux Debian运维方法以及常用命令 二、运维方法 Linux Debian系统的运维涉及到各种任务,包括系统安装、配置、更新和维护,以及故障排查和性能优化等。下面是一些常用的运维命令: 1、以下是部分命令注释 1. apt-ge…...
【涵子来信】——步入中学,日积跬步,以致千里
大家好: 我是涵子,好久没有发文,今天发个文。 如果说,给你一次再入中学的机会,你会怎么想?对于刚刚步入中学的我,目前状况尚好,洛谷最近刷得紧,看看我的洛谷。 好的&…...
【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
<template><div :class"$options.name"><div class"sg-head">接口代码生成工具</div><div class"sg-container"><div class"sg-start "><div style"margin-bottom: 10px;">接口地…...
数据库相关基础知识
第一章 概念 1、数据:描述事物的符号记录称为数据。特点:数据和关于数据的解释不可分。 2、数据库:长期存储在计算机内、有组织、可共享的大量的数据的集合。数据库中的数据按照一定的数据模型组织、描述和存储,具有较小的冗余度、…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
