flutter Completer防抖

158 阅读2分钟

实现如下:

import 'dart:async';

class Debouncer {
  final Duration delay;
  Completer<void>? _completer;
  Timer? _timer;

  Debouncer({required this.delay});

  void run(Future<void> Function() action) {
    // 如果之前的操作还没有完成,取消它

    if (_completer != null && !_completer!.isCompleted) {
      _completer!.completeError('Cancelled');
    }

    _completer = Completer<void>();

    // 重置计时器

    _timer?.cancel();
    _timer = Timer(delay, () async {
      if (_completer!.isCompleted) {
        // 如果任务已经被取消,不执行操作

        return;
      }

      try {
        await action();
        if (!_completer!.isCompleted) {
          _completer!.complete();
        }
      } catch (error) {
        if (!_completer!.isCompleted) {
          _completer!.completeError(error);
        }
      }
    });

    // 处理取消操作

    _completer!.future.catchError((error) {
      print('操作被取消: $error');
    });
  }

  void cancel() {
    if (_completer != null && !_completer!.isCompleted) {
      _completer!.completeError('Cancelled');
    }
    _timer?.cancel();
  }
}

测试代码:

import 'package:flutter/material.dart';
import 'package:test_app/Debouncer.dart';

class TestPage extends StatefulWidget {
  const TestPage({super.key});

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  Debouncer obj = Debouncer(delay: const Duration(seconds: 1));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          children: [
            ElevatedButton(
                onPressed: () {
                  obj.run(() async {
                    print('执行任务1');
                  });

                  obj.run(() async {
                    print('执行任务2');
                  });

                  obj.run(() async {
                    print('执行任务3');
                  });

                  // obj.cancel();
                  Future.delayed(const Duration(seconds: 2), () {
                    obj.run(() async {
                      print('Action after delay');
                    });
                  });
                },
                child: const Text('start')),
          ],
        ),
      ),
    );
  }
}

点击1次按钮:
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 执行任务3
flutter: Action after delay

连续多次点击按钮:
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: 操作被取消: Cancelled
flutter: Action after delay