Flutter对象状态动态监听Watcher
场景:当一个表单需要在表单全部或者特定项赋值后才会让提交按钮可点击。
1.普通实现方式:
///场景:检查[test11][test12][test13]均不为空时做一些事情,例如提交按钮变成可点击String? test11;String? test12;int? test13;///当需要检查[test11][test12][test13]是否全部有值时需要这么做。///1.给[test11][test12][test13]设置监听,或者在他们赋值的时候每次调用2检查。///2.检查三个值的状态if(test11!=null&&test12!=null&&test12!=null){///print [test11][test12][test13]均不为空。}
2.使用Watcher方式实现:
///使用[WatchableObject]配合[Watcher]监测///1.只需要把String、int、bool、等对象用[WatchableObject]代替。WatchableObject test1 = WatchableObject();WatchableObject test2 = WatchableObject();WatchableObject test3 = WatchableObject();///2.使用[Watcher]单例绑定对象。Watcher().bindObject([test1, test2, test3]);///3.检查回调Watcher().check((allCheck) {print("?????????????????????=$allCheck");});///4.模拟不同时间赋值Future.delayed(Duration(seconds: 3), () {test1.setValue("1");});Future.delayed(Duration(seconds: 6), () {test2.setValue("123");});Future.delayed(Duration(seconds: 8), () {test3.setValue(123);});///退出界面时清除Watcher使用得内存@overridevoid dispose() {super.dispose();Watcher().clear();}
logcat输出:
方式1和方式2都能达到效果,但是方式1需要对每一个变量进行监听,在每一个赋值的地方得检查所有得值是否都已有了值,这样实现的出错率就会变得很高。方式2则是利用变量托管,托管类已实现了对变量的赋值的监听,只要使用托管类WatchableObject包装变量,则可以实时监听到变量的赋值变化,所以代码上,对变量的使用不会再对变量进行任何监听和处理,统一会由Watcher类进行回调处理。方式1的缺点就是代码混乱,容易出错。方式2的优点可以解决方式1的缺点,但是缺点是使用到Watcher的地方,变量必须交给WatchableObject托管,导致定义变量的时候变得麻烦,但是这个只要使用习惯了,确可以忽略该缺点。
喜欢这种方式的或者有需求用得到的朋友来撸代码吧:
WatchableObject类:
import 'dart:math';import 'package:kq_flutter_widgets/widgets/listener/object_watcher/watcher.dart';
import 'package:kq_flutter_widgets/widgets/listener/object_watcher/watcher_callback.dart';///可观察对象,
///[T]可观察的对象类型。
///例如:传入的是String,则会持有String对象,
///并可以设置[watcher]观察绑定的String对象值的变化。
class WatchableObject<T> {T? _watchableObject;double? _uuid;///初始值WatchableObject({T? init}) {setValue(init);}///设置值void setValue(T? other) {_watchableObject = Watcher().value(getUuid(), other);}///设置观察者void watcher(WatcherCallback watcherCallback) {Watcher().watcher(getUuid(), watcherCallback);}///获取值T? value() {return _watchableObject;}///获取uuiddouble getUuid() {return _uuid ??= Random().nextDouble();}
}
WatcherCallback类:
///回调
class WatcherCallback<T> {///值改变回调函数,///[object]改变的值。final Function(T? object) onChanged;WatcherCallback(this.onChanged);
}
Watcher类:
import 'package:kq_flutter_widgets/widgets/listener/object_watcher/watchable_object.dart';
import 'package:kq_flutter_widgets/widgets/listener/object_watcher/watcher_callback.dart';///对象观察者
class Watcher {Watcher._internal();factory Watcher() => _instance;static final Watcher _instance = Watcher._internal();final Map<double, WatcherCallback> _objectWatchers = {};final List<WatchableObject> _objects = [];final Map<double, bool> _bindObjects = {};///绑定对象,///[objects]绑定的一组对象。void bindObject(List<WatchableObject> objects) {clear();_objects.addAll(objects);for (WatchableObject str in objects) {_bindObjects.putIfAbsent(str.getUuid(), () => _checkObject(str.value()));}}///检查绑定的对象是否已全部赋值,///[callback]每次赋值都会回调,///[allCheck]是否全部已赋值,是则返回true,不是则返回false。void check<T>(Function(bool allCheck) callback) {for (WatchableObject str in _objects) {str.watcher(WatcherCallback((object) {_bindObjects.update(str.getUuid(),(value) => _checkObject(object),);_realCheck(callback);},),);}_realCheck(callback);}bool _checkObject<T>(T object) {return object is String ? object.isNotEmpty : object != null;}void _realCheck(Function(bool allCheck) callback) {bool isAllCheck = true;_bindObjects.forEach((key, value) {if (!value) {isAllCheck = false;return;}});callback.call(isAllCheck);}///清除内存。void clear() {_objects.clear();_bindObjects.clear();_objectWatchers.clear();}///绑定回调执行,///需要[WatchableObject]对象的[uuid]做为键值获取对象绑定。T? value<T>(double uuid, T? other) {_objectWatchers[uuid]?.onChanged(other);return other;}///绑定设置,///需要[WatchableObject]对象的[uuid]做为键值,///[watcherCallback]绑定的回调。void watcher(double uuid, WatcherCallback watcherCallback) {_objectWatchers.putIfAbsent(uuid, () => watcherCallback);}
}
相关文章:

Flutter对象状态动态监听Watcher
场景:当一个表单需要在表单全部或者特定项赋值后才会让提交按钮可点击。 1.普通实现方式: ///场景:检查[test11][test12][test13]均不为空时做一些事情,例如提交按钮变成可点击String? test11;String? test12;int? test13;///当…...

期权分仓开户资金是否安全?具体保障措施有哪些?
网上关于期权分仓系统的真假一直都没有定论,两方人的争论也让很多没有接触过期权分仓系统的人摸不着头脑,那么期权分仓靠谱吗?资金在里面安全吗?下文为大家科普期权分仓开户资金是否安全?具体保障措施有哪些? 一、期权…...
Unity Mac踩坑日记
1、读取外部文件夹使用IO,读取StreamingAsset或者Unity定义文件夹或者服务器文件使用www或者UnityRequest 2、mac下使用www 需要添加前缀:"file://" 3、Mac下的Rider很好用,断点调试也很方便 4、改变文件编码格式,使…...

什么是负载均衡
前提概述 关于负载均衡,我会从四个方面去说 1. 负载均衡产生的背景 2. 负载均衡的实现技术 3. 负载均衡的作用范围 4. 负载均衡的常用算法 负载均衡的诞生背景 在互联网发展早期,由于用户量较少、业务需求也比较简单。对于软件应用,我们只需要…...
尽管价格走势平淡,但DeFi领域仍然非常有趣
DEX代表加密货币交易的创新,就在去年,这些去中心化、非托管平台的活动与CEX比相形见绌,但自那时以来,DEX已经迎头赶上,并在几个月内超越了中心化服务交易量,让用户能够更好地控制自己的资产和进行新类型的交…...
RCU安全引用计数
原文网址:https://lwn.net/Articles/93617 原文作者:Corbet 原文时间:2004年7月14日 内核提供了一种用于实现引用计数的简单机制kref;该机制是今年3月份完成的。kref机制的核心思想是,提供支持原子操作的计数器&…...

Linux 可重入、异步信号安全和线程安全
可重入函数 当一个被捕获的信号被一个进程处理时,进程执行的普通的指令序列会被一个信号处理器暂时地中断。它首先执行该信号处理程序中的指令。如果从信号处理程序返回(例如没有调用exit或longjmp),则继续执行在捕获到信号时进程…...

WPF中手写地图控件(3)——动态加载地图图片
瓦片增加一个Loading动画 可以查看我的另一个博客WPF中自定义Loading图 从中心扩散 进行从里到外的扩散,方向是上左下右。如下图所示 于是我们可以定义一个拥有坐标X跟Y的集合,他允许这个集合,内部使用枚举器的MoveNext自动排序…...

智慧充电桩物联网方案架构
智慧充电桩物联网采用“云-管-边-端”的边缘计算物联网架构,融合5G、AI、Wi-Fi 6等技术,实现充电基础设施由数字化向智能化演进。智慧充电桩物联网方案架构设计,如下图所示: 云端: 物联网平台具备广泛协议的南向接入…...

C语言基础之——操作符(上)
本篇文章,我们将展开讲解C语言中的各种常用操作符,帮助大家更容易的解决一些运算类问题。 这里提醒一下小伙伴们,本章知识会大量涉及到二进制序列,不清楚二进制序列的小伙伴,可以去阅读我的另一篇文章《数据在内存中的…...
手写链式调用
遇到一个有趣的题目,做个笔记 实现一个arrange函数,可以进行时间和工作调度 //[> …]表示调用函数后的打印内容 //arrange(‘William’).execute(); //> William is notified //arrange(‘William’).do(‘commit’).execute(); //>William …...

DETRs with Collaborative Hybrid Assignments Training论文笔记
Title:[DETRs with Collaborative Hybrid Assignments Training Code 文章目录 1. Motivation2. one to one VS one to many3. Method(1)Encoder feature learning(2)Decoder attention learning 1. Motivation 当前…...

慧程HiperM3系列工业物联网、MES平台
产品链接:慧程产品主页...

SHELL 基础 入门(三) Bash 快捷键 命令执行顺序,详解通配符
目录 Bash 常用快捷键 输入输出重定向 << 用法 输出重定向 命令执行顺序 ; 分号 && || 通配符 传统通配符 ? * [ ] [ - ] [ ^ ] 常用字符 强调 : { } 生成序列 Bash 常用快捷键 Ctrl A 把光…...

nvm安装使用教程
文章目录 下载配置安装最新稳定版 node安装指定版本查看版本切换版本删除版本 常见问题安装node后 显示拒绝访问的问题使用cnpm会报错的问题降低cnpm版本npm镜像 下载 NVM for Windows 下载地址:https://link.juejin.cn/?targethttps%3A%2F%2Fgithub.com%2Fcoreyb…...
【Android】JUnit和Espresso单元测试新手快速入门
引入依赖 android {defaultConfig {testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}}dependencies {testImplementation junit:junit:4.13.2androidTestImplementation androidx.test.ext:junit:1.1.0androidTestImplementation androidx.tes…...
8.4 【C语言】通过指针引用字符串
8.4.1 字符串的引用方式 在C程序中,字符串是存放在字符数组中的。想引用一个字符串,可以用以下两种方法。 (1)用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符,也可以通过数组名和格…...

【广州华锐视点】AR配电所巡检系统:可视化巡检利器
随着科技的发展,人工智能、大数据等技术逐渐应用于各个领域,为人们的生活带来便利。在电力行业,AR(增强现实)技术的应用也日益广泛。AR配电所巡检系统作为一种新型的巡检方式,可以实现多种功能,提高巡检效率࿰…...

微服务中间件--http客户端Feign
http客户端Feign http客户端Feigna.Feign替代RestTemplateb.自定义Feign的配置c.Feign的性能优化d.Feign的最佳实践分析e.Feign实现最佳实践(方式二) http客户端Feign a.Feign替代RestTemplate 以前利用RestTemplate发起远程调用的代码: String url "http:…...

C语言学习系列-->【关于qsort函数的详解以及它的模拟实现】
文章目录 一、概述二、qsort函数参数介绍三、qsort实现排序3.1 qsort实现整型数组排序3.2 qsort实现结构体数组排序 四、模拟实现qsort函数 一、概述 对数组的元素进行排序 对数组中由 指向的元素进行排序,每个元素字节长,使用该函数确定顺序。 此函数使…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...