Flutter可清空计时器插件emptyable_timer的使用

Flutter可清空计时器插件emptyable_timer的使用

特性

  • 可以定义为 EmptyableTimer timer = EmptyableTimer.empty 而不是 Timer? timer
  • 可以检查它是否已取消(在某些情况下,它可能是非活动状态但未被取消)。

动机

考虑以下示例:

class SomeClassWithRegularTimer {
  SomeClassWithRegularTimer() {
    _init();
  }
  Timer? _timer;

  Future<void> _init() async {
    await _someDelayedRequest();
    _timer = Timer(const Duration(seconds: 2), _someHeavyDelayedRequest);
  }

  Future<void> _someDelayedRequest() => Future.delayed(Duration.zero);
  Future<void> _someHeavyDelayedRequest() async {
    await Future.delayed(const Duration(seconds: 30));
    print('_someHeavyDelayedRequest finished');
  }

  void dispose() {
    _timer?.cancel();
  }
}

在这种情况下,尽管调用了方法 [dispose],但方法 _someHeavyDelayedRequest() 仍然会运行:

void main() {
  final someClassWithRegularTimer = SomeClassWithRegularTimer();
  someClassWithRegularTimer.dispose();
}

解决方案

作为解决方案之一,我们可以使用 EmptyableTimer 及其 empty 构造函数。考虑以下示例:

class SomeClassWithEmptyableTimer {
  SomeClassWithEmptyableTimer() {
    _init();
  }
  // 定义一个非空定时器
  EmptyableTimer _timer = EmptyableTimer.empty();

  Future<void> _init() async {
    await _someDelayedRequest();
    // 检查是否已取消
    if (_timer.isCanceled) {
      return;
    }
    _timer =
        EmptyableTimer(const Duration(seconds: 2), _someHeavyDelayedRequest);
  }

  Future<void> _someDelayedRequest() => Future.delayed(Duration.zero);
  Future<void> _someHeavyDelayedRequest() async {
    await Future.delayed(const Duration(seconds: 30));
    print('_someHeavyDelayedRequest finished');
  }

  void dispose() {
    // 直接调用取消方法
    _timer.cancel();
  }
}

我们可以在取消空计时器后检查 isCanceled 属性:

void main() {
  final someClassWithEmptyableTimer = SomeClassWithEmptyableTimer();
  someClassWithEmptyableTimer.dispose();
}

在这种情况下,方法 _someHeavyDelayedRequest() 将永远不会被调用。

完整示例代码

import 'dart:async';

import 'package:emptyable_timer/emptyable_timer.dart';

void main() {
  // 使用普通计时器的解决方案
  //
  // 尽管调用了dispose方法,
  // 但是方法 _someHeavyDelayedRequest() 仍然会被执行
  final someClassWithRegularTimer = SomeClassWithRegularTimer();
  someClassWithRegularTimer.dispose();

  // 使用EmptyableTimer的解决方案
  //
  // 取消注释以下代码进行测试
  // final someClassWithEmptyableTimer = SomeClassWithEmptyableTimer();
  // someClassWithEmptyableTimer.dispose();
}

class SomeClassWithRegularTimer {
  SomeClassWithRegularTimer() {
    _init();
  }
  Timer? _timer;

  Future<void> _init() async {
    await _someDelayedRequest();
    _timer = Timer(const Duration(seconds: 2), _someHeavyDelayedRequest);
  }

  Future<void> _someDelayedRequest() => Future.delayed(Duration.zero);
  Future<void> _someHeavyDelayedRequest() async {
    await Future.delayed(const Duration(seconds: 30));
    print('_someHeavyDelayedRequest finished');
  }

  void dispose() {
    _timer?.cancel();
  }
}

class SomeClassWithEmptyableTimer {
  SomeClassWithEmptyableTimer() {
    _init();
  }
  // 定义一个非空定时器
  EmptyableTimer _timer = EmptyableTimer.empty();

  Future<void> _init() async {
    await _someDelayedRequest();
    // 检查是否已取消
    if (_timer.isCanceled) {
      return;
    }
    _timer =
        EmptyableTimer(const Duration(seconds: 2), _someHeavyDelayedRequest);
  }

  Future<void> _someDelayedRequest() => Future.delayed(Duration.zero);
  Future<void> _someHeavyDelayedRequest() async {
    await Future.delayed(const Duration(seconds: 30));
    print('_someHeavyDelayedRequest finished');
  }

  void dispose() {
    // 直接调用取消方法
    _timer.cancel();
  }
}

更多关于Flutter可清空计时器插件emptyable_timer的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter可清空计时器插件emptyable_timer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用emptyable_timer插件来实现可清空计时器的代码示例。这个插件允许你创建一个可以启动、暂停和重置的计时器。

首先,确保你的Flutter项目已经添加了emptyable_timer依赖。你可以在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  emptyable_timer: ^最新版本号  # 请替换为实际最新版本号

然后运行flutter pub get来安装依赖。

接下来,我们来看一个完整的使用示例:

import 'package:flutter/material.dart';
import 'package:emptyable_timer/emptyable_timer.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Emptyable Timer Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TimerScreen(),
    );
  }
}

class TimerScreen extends StatefulWidget {
  @override
  _TimerScreenState createState() => _TimerScreenState();
}

class _TimerScreenState extends State<TimerScreen> {
  EmptyableTimerController _timerController;
  Duration _currentDuration = Duration.zero;

  @override
  void initState() {
    super.initState();
    _timerController = EmptyableTimerController();
    _timerController.addListener(() {
      setState(() {
        _currentDuration = _timerController.duration;
      });
    });
  }

  @override
  void dispose() {
    _timerController.dispose();
    super.dispose();
  }

  void _startTimer() {
    _timerController.reset();
    _timerController.start();
  }

  void _pauseTimer() {
    _timerController.pause();
  }

  void _resetTimer() {
    _timerController.reset();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Emptyable Timer Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              _currentDuration.toString().split('.').first,
              style: TextStyle(fontSize: 48),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _startTimer,
              child: Text('Start'),
            ),
            ElevatedButton(
              onPressed: _pauseTimer,
              child: Text('Pause'),
            ),
            ElevatedButton(
              onPressed: _resetTimer,
              child: Text('Reset'),
            ),
          ],
        ),
      ),
    );
  }
}

代码解释:

  1. 依赖导入:首先,在pubspec.yaml文件中添加emptyable_timer依赖。

  2. 创建主应用:在MyApp类中,我们定义了一个基本的Flutter应用,它使用MaterialApp作为根组件。

  3. 计时器屏幕TimerScreen是一个有状态的组件,它包含了计时器的逻辑和UI。

  4. 初始化计时器控制器:在initState方法中,我们初始化了EmptyableTimerController并添加了一个监听器,以便在计时器更新时刷新UI。

  5. 计时器控制方法:定义了三个方法来控制计时器:_startTimer_pauseTimer_resetTimer

  6. 构建UI:在build方法中,我们创建了一个简单的UI,显示当前计时器的时长,并提供三个按钮来控制计时器。

这个示例展示了如何使用emptyable_timer插件来创建一个基本的计时器应用。你可以根据需要进一步扩展和自定义这个示例。

回到顶部