commit c184721f064ddf21ebff24e52dce338a33a262cd Author: DESKTOP-I3JPKHK\wy <1111> Date: Fri Dec 12 15:05:19 2025 +0800 提交异步防抖或者节流操作 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd5eb98 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..9e2f122 --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "ac4e799d237041cf905519190471f657b657155a" + channel: "stable" + +project_type: package diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..41cc7d8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba75c69 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4a260d8 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..a5744c1 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/lib/async_throttle.dart b/lib/async_throttle.dart new file mode 100644 index 0000000..99f9250 --- /dev/null +++ b/lib/async_throttle.dart @@ -0,0 +1,79 @@ +import 'package:easy_debounce/easy_debounce.dart'; +import 'package:easy_debounce/easy_throttle.dart'; + +/// 异步防抖/节流工具类 +class AsyncThrottle { + // 私有构造函数,防止外部实例化 + AsyncThrottle._(); + + // 懒汉式单例 - 使用 late final 延迟初始化 + static final AsyncThrottle _instance = AsyncThrottle._(); + + // 获取单例实例 + static AsyncThrottle get instance => _instance; + + // 存储异步任务锁状态 + final Map _asyncLocks = {}; + + /// 异步执行方法 - 防止弱网重复点击 (无 Loading UI) + /// + /// 结合了 时间策略(防抖/节流)和 异步任务状态锁。 + /// 只有当满足以下两个条件时才会执行: + /// 1. 当前没有正在执行的同名任务 (Task Lock - 解决弱网长耗时问题) + /// 2. 满足时间策略 (Time Policy - 解决快速连点问题) + /// + /// [tagId]: 唯一标识符 + /// [onExecute]: 要执行的异步方法 + /// [duration]: 时间间隔,默认 300ms + /// [enableDebounce]: 是否启用防抖模式。 + /// - true: 使用防抖 (Debounce) - 延迟执行,最后一次点击生效(适合搜索、输入) + /// - false: 使用节流 (Throttle) - 立即执行,忽略后续点击(默认,适合按钮点击) + Future execute( + String tagId, + Future Function() onExecute, { + Duration duration = const Duration(milliseconds: 300), + bool enableDebounce = false, + }) async { + // 1. 检查异步锁 (防止上一个请求未回来时重复点击) + // 无论是防抖还是节流,只要任务还在执行中,都不应重入 + if (isExecuting(tagId)) return; + + if (enableDebounce) { + // === 防抖模式 (Debounce) === + // 延迟 duration 后执行,如果在期间再次调用,会重新计时 + EasyDebounce.debounce(tagId, duration, () async { + // 防抖触发时,再次检查锁(双重检查) + if (isExecuting(tagId)) return; + + _asyncLocks[tagId] = true; + try { + await onExecute(); + } finally { + _asyncLocks.remove(tagId); + } + }); + } else { + // === 节流模式 (Throttle) - 默认 === + // 立即执行,并在 duration 内忽略后续调用 + // throttle 返回 true 表示被节流(忽略),false 表示获得了执行权 + final isThrottled = EasyThrottle.throttle(tagId, duration, () {}); + + // 如果被节流了,直接返回 + if (isThrottled) return; + + // 获得执行权,加锁并执行 + _asyncLocks[tagId] = true; + try { + await onExecute(); + } finally { + _asyncLocks.remove(tagId); + } + } + } + + /// 检查任务是否正在执行 + bool isExecuting(String tagId) => _asyncLocks[tagId] ?? false; + + /// 强制取消所有锁(慎用) + void clearAllLocks() => _asyncLocks.clear(); +} diff --git a/lib/yx_async_throttle_flutter.dart b/lib/yx_async_throttle_flutter.dart new file mode 100644 index 0000000..d6ea609 --- /dev/null +++ b/lib/yx_async_throttle_flutter.dart @@ -0,0 +1,3 @@ +library yx_async_throttle_flutter; + +export 'package:yx_async_throttle_flutter/async_throttle.dart'; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..0edf10e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,55 @@ +name: yx_async_throttle_flutter +description: "A new Flutter package project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.9.2 + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + easy_debounce: ^2.0.3 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/test/yx_async_throttle_flutter_test.dart b/test/yx_async_throttle_flutter_test.dart new file mode 100644 index 0000000..d148e35 --- /dev/null +++ b/test/yx_async_throttle_flutter_test.dart @@ -0,0 +1,10 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:yx_async_throttle_flutter/yx_async_throttle_flutter.dart'; + +void main() { + test('AsyncThrottle instance check', () { + final throttle = AsyncThrottle.instance; + expect(throttle, isNotNull); + }); +}