如何在Flutter中实现持久秒表?

2023-11-22

我正在 flutter 中实现一个计时器。这是应用程序的结构。

页面 A(包含一些列表,用户单击这些列表并将其带到计时器页面)。 页面 B 格式,运行计时器。我能够正确运行计时器/秒表,但是当我按页面 B 上的后退按钮时,我会在处理错误后调用 setstate() 。我知道这是预期的行为。 如果我在处置时使用timer.cancel(),我不会收到错误,但计时器将停止运行。即使我导航到页面A或说任何其他新页面(小部件),计时器/秒表也应该继续运行。 我知道使用侦听器和 WidgetBindingObserver 可能可以做到这一点,但我对实现它没有明确的了解。希望我能在这个问题上得到一些帮助。

页面B的构建类:

  Widget build(BuildContext context) {
return Scaffold(
    appBar: AppBar(
      leading: new IconButton(icon: new Icon(Icons.arrow_back), onPressed: ()async{
        Navigator.pop(context,widget._elapsedTime);
      }),
      title: Text("widget.title"),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            '$_elapsedTime'),
          RaisedButton(
            child: Text('Start'),
            onPressed: () { 
              if(watch.isRunning){
                stopWatch();
              }
              else{
               startWatch();
              }
            },
          ),

        ],
      ),
    ));

启动观察功能:

startWatch() {
watch.start();
timer = new Timer.periodic(new Duration(milliseconds:1000), updateTime);}

每秒调用一次的更新时间函数:

updateTime(Timer timer) {
   if (watch.isRunning) {
   print(_elapsedTime);
   var time= formatedTime(watch.elapsedMilliseconds);
   print("time is"+time);
   setState(() {
        _elapsedTime = time;
   });
 }

这是一个最小的工作解决方案。关键点:

  • 介绍一个TimerService隔离计时器功能的类
  • TimerService实施ChangeNotifier,您可以订阅以接收更改。
  • An InheritedWidget用于为应用程序的所有小部件提供服务。这个继承的小部件包装了您的应用程序小部件。
  • AnimatedBuilder用于接收来自的更改ChangeNotifier。订阅是自动处理的(无需手动addListener/removeListener).

import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  final timerService = TimerService();
  runApp(
    TimerServiceProvider( // provide timer service to all widgets of your app
      service: timerService,
      child: MyApp(),
    ),
  );
}

class TimerService extends ChangeNotifier {
  Stopwatch _watch;
  Timer _timer;

  Duration get currentDuration => _currentDuration;
  Duration _currentDuration = Duration.zero;

  bool get isRunning => _timer != null;

  TimerService() {
    _watch = Stopwatch();
  }

  void _onTick(Timer timer) {
    _currentDuration = _watch.elapsed;

    // notify all listening widgets
    notifyListeners();
  }

  void start() {
    if (_timer != null) return;

    _timer = Timer.periodic(Duration(seconds: 1), _onTick);
    _watch.start();

    notifyListeners();
  }

  void stop() {
    _timer?.cancel();
    _timer = null;
    _watch.stop();
    _currentDuration = _watch.elapsed;

    notifyListeners();
  }

  void reset() {
    stop();
    _watch.reset();
    _currentDuration = Duration.zero;

    notifyListeners();
  }

  static TimerService of(BuildContext context) {
    var provider = context.inheritFromWidgetOfExactType(TimerServiceProvider) as TimerServiceProvider;
    return provider.service;
  }
}

class TimerServiceProvider extends InheritedWidget {
  const TimerServiceProvider({Key key, this.service, Widget child}) : super(key: key, child: child);

  final TimerService service;

  @override
  bool updateShouldNotify(TimerServiceProvider old) => service != old.service;
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Service Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    var timerService = TimerService.of(context);
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: AnimatedBuilder(
          animation: timerService, // listen to ChangeNotifier
          builder: (context, child) {
            // this part is rebuilt whenever notifyListeners() is called
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text('Elapsed: ${timerService.currentDuration}'),
                RaisedButton(
                  onPressed: !timerService.isRunning ? timerService.start : timerService.stop,
                  child: Text(!timerService.isRunning ? 'Start' : 'Stop'),
                ),
                RaisedButton(
                  onPressed: timerService.reset,
                  child: Text('Reset'),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Flutter中实现持久秒表? 的相关文章

随机推荐

  • 禁用 PHPhotoLibrary 中删除请求的确认

    我想做的是将视频保存到 PHPhotoLibrary 然后在应用程序中上传到客户端远程服务器完成时删除它们 基本上 照片库充当临时存储 以添加额外的安全层 以防万一发生任何故障 我已经将我的视频保存在应用程序目录中 Problem 问题是要
  • 使用 Java 从 Github 下载二进制文件

    我正在尝试下载此文件 http github com downloads TheHolyWaffle ChampionHelper ChampionHelper 4 jar 用下面的方法 它似乎不起作用 我收到一个空 损坏的文件 Strin
  • 有没有办法使用curse在同一终端上创建单独的显示和输入?

    我想编写一个命令行程序来生成以下用户界面 A B A 是一个单独的进程 它循环并显示实时事件列表 它会自动刷新 B 是命令提示符 它固定在底部并有命令历史记录 我知道一些命令行 IRC 程序会执行此操作 因此它一定是可能的 如果您能给我一个
  • Stargazer 输出是代码,而不是表格

    我正在尝试使用 RStudio 中的 stargazer 包来生成数据汇总表 由于某种原因 当我使用 html 或 Latex 代码时 我无法查看输出中的表格 但当我输出为文本时 我可以看到它 一个例子 library stargazer
  • 类型错误:google.visualization.DataTable 不是构造函数

    在我的网页上有一个谷歌地图 以及三个图表 当页面加载时 地图很好 但图表要么不加载 要么只有一两个加载 不断收到错误 TypeError google visualization DataTable 不是构造函数 function load
  • 获取返回 StreamedContent 的 的具体 URL

    为了使用灯箱 我需要一个指向由以下命令生成的图像的链接
  • 如何在另一个 groovy 脚本中简单地导入 groovy 文件

    groovy tree lib GTemplate class GTemplate groovy Simple groovy class GTemplate static def toHtml this newInstance toHtml
  • Android 中的 Base64 图像转换导致图像损坏

    我需要将 JSON 上传到服务器 因此我尝试使用 base64 对其进行编码 然后通过 JSON 发送它 但在服务器端解码图像时 图像显示已损坏 我什至尝试过在线 Base64 到图像转换器 结果是相同的 这是我的活动代码 在从图库或相机中
  • 在 Scala 2.10 中通过反射查找类型参数?

    使用类型标签 我能够see某种类型的参数 scala gt import scala reflect runtime universe import scala reflect runtime universe scala gt typeO
  • 如何从 CMD 运行 Pip 命令

    据我了解 Python 2 7 9 附带安装了 Pip 但是当我尝试从 CMD Windows 执行 Pip 命令时 出现以下错误 pip is not recognized as an internal or external comma
  • 如何在Android Studio中指定JDK版本?

    Android Studio 给我一个 Gradle 构建错误 如下所示 Error 3 22 compileSdkVersion android 22 requires compiling with JDK 7 现在它给了我这些可点击的提
  • 如何正确处理Python中的循环模块依赖?

    尝试找到一种良好且正确的模式来处理 Python 中的循环模块依赖关系 通常 解决方案是删除它 通过重构 然而 在这种特殊情况下 我们确实希望拥有需要循环导入的功能 EDIT 根据下面的答案 此类问题通常的攻击角度是重构 然而 为了这个问题
  • Mac 上的 PDO MySQL 驱动程序

    我有一台大约一年前安装的自定义 PHP 5 的 Mac 我记得我花了整个星期天的时间 编译了大约 20 次才能把它做好 我拥有的 MySQL 来自熵并且是预编译的 现在我需要让 PDO 与 MySQL 驱动程序一起工作 但驱动程序尚未安装
  • 在c二进制中,测试数字是否在范围内

    这是我无法解开的谜题的一部分 该函数接受三个输入 第一个是 int 第二个是下界 第三个是上限 我需要测试第一个数字是否在下限和上限内 包括下限和上限 如果在范围内则返回1 否则返回0 问题是我只能使用 lt lt gt gt 操作 并且只
  • linux、C++、xft:如何使用它?

    我尝试使用 Xft tutorial 好吧 让他们称之为教程 看起来像是在朝鲜营地写的 我也发现了这个one 那么让我尝试一步一步地进行 g XftTest cc lX11 lXft pkg config cflags freetype2
  • 为什么我会收到此 WCF 错误消息?

    当我调用 WCF 服务时 出现以下错误 我在这里缺少什么 System String with data contract name ArrayOfstring http schemas microsoft com 2003 10 Seri
  • DRF 光标分页示例

    我正在尝试设置使用 DRF 进行光标分页获取交易记录列表 按创建日期排序 我不知道如何执行初始请求 因为我在那个阶段还不知道光标 令人惊讶的是 我找不到这方面的例子 另外 有没有办法使用 CursorPagination 设置每个请求的页面
  • SwiftUI @Binding 不刷新视图

    我有一个简单的主 详细信息界面 其中详细信息视图修改数组中的项目 使用下面的代码 模型已正确更新 但 SwiftUI 不会刷新视图以反映更改 Model struct ProduceItem Identifiable let id UUID
  • 插入时保持 std 向量/列表排序,或全部排序

    假设我的向量 列表中有 30000 个对象 这是我一一补充的 我需要将它们分类 一次排序 如 std sort 更快 还是在我一一添加对象时保持向量 列表排序更快 矢量 列表以后不会被修改 当你在一个接一个地插入元素的同时保持向量列表排序时
  • 如何在Flutter中实现持久秒表?

    我正在 flutter 中实现一个计时器 这是应用程序的结构 页面 A 包含一些列表 用户单击这些列表并将其带到计时器页面 页面 B 格式 运行计时器 我能够正确运行计时器 秒表 但是当我按页面 B 上的后退按钮时 我会在处理错误后调用 s