简体   繁体   English

Flutter:倒数计时器

[英]Flutter: Countdown Timer

I am trying to create a timer app that has multiple countdown timers for different tasks.我正在尝试创建一个计时器应用程序,该应用程序具有用于不同任务的多个倒数计时器。 The issue, I am facing is that, if I start a one-timer, and press the back button, the timer stops.我面临的问题是,如果我启动一个计时器,然后按下后退按钮,计时器就会停止。 So I want, that timer to run till either it is being paused or the timer ends and alerts the user or the app is destroyed.因此,我希望该计时器一直运行到它被暂停或计时器结束并提醒用户或应用程序被破坏为止。 Help me how can I do this using Flutter?帮助我如何使用 Flutter 做到这一点?

Any Sample Code Will be Appreciated?任何示例代码都会受到赞赏?

enter link description here 在此处输入链接描述

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),
              ),

When you pop back, any "state" in the widget will be destroyed.当您弹回时,小部件中的任何“状态”都将被销毁。

There are three kinds of method you can do to prevent "state" being destroyed (or memory release):您可以采取三种方法来防止“状态”被破坏(或内存释放):

  • Using static property使用静态属性
  • Using state manager by Provider Provider使用状态管理器
  • Using state manager by static instance通过静态实例使用状态管理器

There are still many method to manage your state, but not mention here, see details in this repo还有很多方法可以管理你的状态,但这里不提,详见这个 repo

Static property静态属性

Static property is something like variable outside your class, like:静态属性类似于类之外的变量,例如:

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

class MyWidget {}

Rather, it is class based variable.相反,它是基于类的变量。 Which means it can help you describe the variable more.这意味着它可以帮助您更多地描述变量。 like class Dog can has a static property static final footShouldHave = 4 .像类Dog可以具有静态属性static final footShouldHave = 4 Class based programing is popular because it can manage your state and any logic action "inside" the class, and make it easier to understand and code.基于类的编程很受欢迎,因为它可以管理您的状态和“类内部”的任何逻辑操作,并使其更易于理解和编码。

When the class is being destroyed (memory release), any "state" inside the class should be pop from stack but not static.当类被销毁(内存释放)时,类内的任何“状态”都应该从堆栈中弹出,而不是静态的。 You can see more detail by knowing how compiler works.通过了解编译器的工作原理,您可以看到更多细节。

In your case, you can do something like:在您的情况下,您可以执行以下操作:

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());
  }
}

Provide state manager by Provider Provider提供状态管理器

Provider is made for flutter and also maintained by flutter team. Provider是为 Flutter 制作的,也由 Flutter 团队维护。 It can make you easy to manage your class by accessing it from context .它可以让您通过从context访问它来轻松管理您的课程。

You can also set up how the class create.您还可以设置类的创建方式。

  • lazy , create only when you need it lazy ,只在需要时创建
  • create in future future创造
  • ... ...

In your case, it should be like:在你的情况下,它应该是这样的:

  1. Build your helper class TimerManager构建你的助手类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. Bind with ProviderProvider绑定
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. Get it from your context .从您的context获取它。

Now when your widget is released, it is still existed in parent context (if their do exist a parent).现在,当您的小部件发布时,它仍然存在于父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());
  }
}

static instance静态实例

Kind of combined method from 1 and 2. 1和2的组合方法。

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

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

  ...
}

Just call it in your widget只需在您的小部件中调用它

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

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

Summary概括

There is no best way to keep your state in generally, but in your case, I recommend Provider method.一般来说,没有最好的方法来保持你的状态,但在你的情况下,我推荐Provider方法。

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

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