簡體   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