繁体   English   中英

Flutter:倒数计时器

[英]Flutter: Countdown Timer

我正在尝试创建一个计时器应用程序,该应用程序具有用于不同任务的多个倒数计时器。 我面临的问题是,如果我启动一个计时器,然后按下后退按钮,计时器就会停止。 因此,我希望该计时器一直运行到它被暂停或计时器结束并提醒用户或应用程序被破坏为止。 帮助我如何使用 Flutter 做到这一点?

任何示例代码都会受到赞赏?

在此处输入链接描述

CountDownController _controller = CountDownController();

CircularCountDownTimer(
                width: MediaQuery.of(context).size.width / 6,
                height: MediaQuery.of(context).size.width / 6,
                duration: 120,
                fillColor: Colors.green,
                ringColor: Colors.white,
                controller: _controller,
                backgroundColor: Colors.white54,
                strokeWidth: 10.0,
                strokeCap: StrokeCap.round,
                isTimerTextShown: true,
                isReverse: false,
                onComplete: () {
                  Notify();
                },
                textStyle: TextStyle(fontSize: 20.0, color: 
      Colors.black),
              ),

当您弹回时,小部件中的任何“状态”都将被销毁。

您可以采取三种方法来防止“状态”被破坏(或内存释放):

  • 使用静态属性
  • Provider使用状态管理器
  • 通过静态实例使用状态管理器

还有很多方法可以管理你的状态,但这里不提,详见这个 repo

静态属性

静态属性类似于类之外的变量,例如:

// prefix "_" for private variable
const _myStaticVar = 'hello world';

class MyWidget {}

相反,它是基于类的变量。 这意味着它可以帮助您更多地描述变量。 像类Dog可以具有静态属性static final footShouldHave = 4 基于类的编程很受欢迎,因为它可以管理您的状态和“类内部”的任何逻辑操作,并使其更易于理解和编码。

当类被销毁(内存释放)时,类内的任何“状态”都应该从堆栈中弹出,而不是静态的。 通过了解编译器的工作原理,您可以看到更多细节。

在您的情况下,您可以执行以下操作:

class MyTimer extends StatlessWidget {
  static DateTime? starter;

  Widget build(context) {
    if (starter == null) {
      starter = DateTime.now();
    }
    final secondPass = (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000;
    final secondLeft = 60 - secondPass;
    return Text(secondLeft.toString());
  }
}

Provider提供状态管理器

Provider是为 Flutter 制作的,也由 Flutter 团队维护。 它可以让您通过从context访问它来轻松管理您的课程。

您还可以设置类的创建方式。

  • lazy ,只在需要时创建
  • future创造
  • ...

在你的情况下,它应该是这样的:

  1. 构建你的助手类TimerManager
class TimerManager {
  final DateTime? starter;

  void startIfNeed() {
    if (starter != null) {
      starter = DateTime.now();
    }
  }

  num get secondLeft => 60 - (DateTime.now().millisecondsSinceEpoch - starter!.millisecondsSinceEpoch) / 1000
}
  1. Provider绑定
class Homepage extends statelessWidget {
  Widget build(context) {
    return TextButton(
      onPressed: () => navigateToTimer(context),
      child: Text('go'),
    );
  }

  void navigateToTimer(Build context) {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (_) => MyTimer()),
    );
  } 
}

void main() {
  runApp(MaterialApp(
    home: Provider<TimerManager>(
      create: () => TimerManager(),
      child: Homepage(),
    )
  ));
}
  1. 从您的context获取它。

现在,当您的小部件发布时,它仍然存在于父context (如果它们确实存在父上下文)。

// remember to import provider to able `context.read()`.
// see more detail in document.
import 'package:provider/provider.dart';

class MyTimer extends StatlessWidget {
  Widget build(context) {
    final manager = context.read<TimerManager>();
    manager.startIfNeed();

    return Text(manager.secondLeft.toString());
  }
}

静态实例

1和2的组合方法。

class TimerManager {
  // make it singleton
  static final TimerManager  instance = TimerManager._();

  // It is now private constructor
  const TimerManager._();

  ...
}

只需在您的小部件中调用它

class MyTimer extends StatlessWidget {
  Widget build(context) {
    TimerManager.instance.startIfNeed();

    return Text(TimerManager.instance.secondLeft.toString());
  }
}

概括

一般来说,没有最好的方法来保持你的状态,但在你的情况下,我推荐Provider方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM