yx_async_throttle_flutter/README.md

4.5 KiB
Raw Blame History

yx_async_throttle_flutter

一个健壮的 Flutter 异步任务防抖Debounce与节流Throttle工具类。

它完美结合了 时间策略Throttle/Debounce异步任务锁Async Task Locking旨在解决复杂场景下如弱网环境或用户快速连点的重复执行问题。

功能特性

  • 双重保护机制:
    • 时间策略: 防止短时间内快速重复点击(基于 easy_debounce
    • 异步锁: 即使时间间隔已过,如果上一个异步任务(如网络请求)尚未完成,也会阻止新任务执行。
  • 节流模式 (Throttle - 默认): 立即执行,并在指定时间内忽略后续调用。非常适合“提交”、“登录”等按钮。
  • 防抖模式 (Debounce): 延迟执行,直到停止调用一段时间后才执行。非常适合“搜索框”、“实时输入校验”。
  • 内存安全: 在防抖模式下正确管理 Completer,防止因任务被取消导致的 await 永久挂起和内存泄漏。
  • 简单易用: 单例调用API 简洁。

快速开始 (Getting Started)

在你的 pubspec.yaml 文件中添加依赖:

dependencies:
  yx_async_throttle_flutter:
    git:
      url: https://gitea.23544.com/wangyang/yx_async_throttle_flutter.git
      ref: 1.0.0

使用指南 (Usage)

1. 基础节流 (按钮防暴力点击)

适用于“提交订单”、“登录”、“保存”等场景。 即使网络很慢(请求耗时 > 500ms或者用户手速很快该函数也能确保在上一个请求完成时间间隔满足之前,不会重复执行。

import 'package:yx_async_throttle_flutter/async_throttle.dart';

void onSubmit() async {
  // 使用唯一的 tagId 标识这个动作
  await AsyncThrottle.instance.execute(
    'submit_order_btn', 
    () async {
      // 你的异步逻辑(例如 API 调用)
      print('正在提交订单...');
      await Future.delayed(Duration(seconds: 2)); // 模拟耗时网络请求
      print('订单提交完成!');
    },
    duration: Duration(milliseconds: 500), // 默认 300ms
    enableDebounce: false, // 默认 false (节流模式)
  );
}

1.1 UI 回调最佳实践(不影响 UI / 不抛到全局)

onTap / onPressed / PopupMenuItem.onTap 这类回调通常不能 await(即使写成 async 也经常没人等待它)。 为了避免 onExecute 内部异常变成 unhandled async error 影响 UI建议用 executeSafe

PopupMenuItem(
  onTap: () {
    AsyncThrottle.instance.executeSafe(
      'withdraw_task',
      controller.withdrawTask,
      onError: (e, s) {
        // 这里做日志/Toast/上报,不影响 UI
      },
    );
  },
  child: ...,
)

2. 防抖模式 (搜索或输入)

适用于搜索框、实时输入联想等场景。只有当用户停止输入指定时间后,才会触发逻辑。

import 'package:yx_async_throttle_flutter/async_throttle.dart';

void onSearchChanged(String query) async {
  await AsyncThrottle.instance.execute(
    'search_input', 
    () async {
      // 只有当用户停止输入 500ms 后才会执行
      print('搜索内容: $query');
      await fetchSearchResults(query);
    },
    duration: Duration(milliseconds: 500),
    enableDebounce: true, // 启用防抖模式
  );
}

3. 清除锁 (可选)

在极少数情况下(例如用户退出登录时),你可能需要强制清除所有内部锁。

AsyncThrottle.instance.clearAllLocks();

核心优势:为什么需要异步锁?

普通的 Throttle 库通常只根据 时间 来控制执行。

典型 Bug 场景: 设定节流时间为 500ms

  1. 用户点击“提交”。请求发出,但网络很慢,耗时 2000ms
  2. 600ms 时(此时节流时间已过),用户因焦急再次点击“提交”。
  3. 问题: 普通 Throttle 库会认为 500ms 已到,允许执行第二次请求,导致 重复下单

本库的解决方案: yx_async_throttle_flutter 会检查 isExecuting 状态。虽然时间已过但因为第一个请求2000ms还在运行第二次点击会被直接拦截从而完美防止重复提交。

💡 最佳实践: 如果在 onExecute 函数内部再添加 Loading 蒙层UI 阻断),配合本插件即可实现 “三层防护”UI 蒙层 + 时间策略 + 异步锁),彻底杜绝任何异常场景下的重复操作。

其他信息

本库底层的时间策略依赖于 easy_debounce