【问题标题】:how to set up a timer in a provider package change notifier?如何在提供程序包更改通知程序中设置计时器?
【发布时间】:2023-01-20 02:06:56
【问题描述】:

我在一个有状态的小部件中设置了一个倒数计时器。 (我跟随了一个 youtube 教程。我是 flutter 的新手)。我想在我的应用程序的其他页面上显示。 所以我在考虑使用 provider 包,因为我将它用于所有其他变量。唯一的问题是我不知道如何将所需的部件转移到提供程序包中,以便我可以从其他页面调用它们。 这是我的代码:

import 'dart:async';
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'constants.dart';

class ChessClock extends StatefulWidget {
  const ChessClock({Key? key}) : super(key: key);

  @override
  State<ChessClock> createState() => _ChessClockState();
}

class _ChessClockState extends State<ChessClock> {
  static const countdownDuration = Duration(minutes: 10);
  Duration duration = Duration();
  Timer? timer;
  bool isCountdown = true;
  @override
  void initState() {
    super.initState();
    Reset();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
    ]);
  }

  void Reset() {
    if (isCountdown) {
      setState(() => duration = countdownDuration);
    } else {
      setState(
        () => duration = Duration(),
      );
    }
  }

  void addTime() {
    final addSeconds = isCountdown ? -1 : 1;
    setState(() {
      final seconds = duration.inSeconds + addSeconds;
      if (seconds < 0) {
        timer?.cancel();
      } else {
        duration = Duration(seconds: seconds);
      }
    });
  }

  void startTimer() {
    timer = Timer.periodic(
      Duration(seconds: 1),
      (_) => addTime(),
    );
  }

  void stopTimer() {
    setState(
      () => timer?.cancel(),
    );
  }

  @override
  void dispose() {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    super.dispose();
  }

  bool isRunningLeft = false;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Row(
          children: [
            Expanded(
              flex: 3,
              child: Container(
                padding: EdgeInsets.all(20),
                child: InkWell(
                  onTap: () {
                    setState(() {
                      isRunningLeft = !isRunningLeft;
                    });
                    isRunningLeft ? startTimer() : stopTimer();
                  },
                  child: Container(
                    width: double.infinity,
                    height: double.infinity,
                    decoration: BoxDecoration(
                      color: isRunningLeft ? kOrange : kBlueGrey900,
                      borderRadius: BorderRadius.circular(30),
                    ),
                    child: Center(
                      child: BuildTimeLeft(),
                    ),
                  ),
                ),
              ),
            ),
            RowSpacers(
                lineColor: kOrange,
                leftSizedBox: 2,
                rightSizedBox: 2,
                containerWidth: 3),
            Expanded(
              flex: 2,
              child: Container(),
            ),
            RowSpacers(
                lineColor: kOrange,
                leftSizedBox: 2,
                rightSizedBox: 2,
                containerWidth: 3),
            Expanded(
              flex: 3,
              child: Container(),
            ),
          ],
        ),
      ),
    );
  }

  Widget BuildTimeLeft() {
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final hours = twoDigits(
      duration.inHours.remainder(60),
    );
    final minutes = twoDigits(
      duration.inMinutes.remainder(60),
    );
    final seconds = twoDigits(
      duration.inSeconds.remainder(60),
    );
    return RotatedBox(
      quarterTurns: 1,
      child: Text(
        '$hours:$minutes:$seconds',
        style: TextStyle(fontSize: 50),
      ),
    );
  }
}

class StopWatchTimers with ChangeNotifier {}

因为时间不是整数之类的基本变量,所以我不确定该怎么做。

非常感谢

【问题讨论】:

    标签: flutter dart flutter-provider


    【解决方案1】:

    为了在 ProviderChangeNotifier 中设置定时器,您需要执行以下操作:

    1. 为您的计时器提供程序创建一个新文件,例如 timer_provider.dart

    2. 在此文件中,创建一个扩展 ChangeNotifier 的新类,并包含计时器的必要变量,例如当前剩余时间、计时器持续时间以及用于跟踪计时器是否正在运行的布尔值。

      class TimerProvider extends ChangeNotifier {
        int _timeRemaining = 0;
        int _duration = 0;
        bool _isRunning = false;
      
        int get timeRemaining => _timeRemaining;
        int get duration => _duration;
        bool get isRunning => _isRunning;
      
        void startTimer(int duration) {
          _duration = duration;
          _timeRemaining = duration;
          _isRunning = true;
          // Add code here to start the actual timer
          notifyListeners();
        }
      
        void stopTimer() {
          _isRunning = false;
          // Add code here to stop the actual timer
          notifyListeners();
        }
      
        void updateTimeRemaining(int newTime) {
          _timeRemaining = newTime;
          notifyListeners();
        }
      }
      
      1. 在您的main.dart 文件中,导入提供程序包并使用提供您的TimerProvider 类的ChangeNotifierProvider 包装您的MaterialApp 小部件。
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return ChangeNotifierProvider(
            create: (context) => TimerProvider(),
            child: MaterialApp(
              // your app code here
            ),
          );
        }
      }
      
      
      1. 在要显示计时器的小部件中,您可以使用Consumer 小部件访问计时器数据并相应地更新 UI。
      class TimerDisplay extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return Consumer<TimerProvider>(
            builder: (context, timer, child) {
              return Text(timer.timeRemaining.toString());
            },
          );
        }
      }
      
      1. 要启动和停止计时器,您可以从应用的其他部分调用TimerProvider 类上的相关函数。
      class StartButton extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return RaisedButton(
            onPressed: () {
              Provider.of<TimerProvider>(context, listen: false).startTimer(60);
            },
            child: Text('Start'),
          );
        }
      }
      
      1. 最后,您需要更新TimerProvider 类中的剩余时间,您可以使用Timer.periodic 来完成。
      class TimerProvider extends ChangeNotifier {
        int _timeRemaining = 0;
        int _duration = 0;
        bool _isRunning = false;
        Timer _timer;
      
        int get timeRemaining => _timeRemaining;
        int get duration => _duration;
        bool get isRunning => _isRunning;
      
        void startTimer(int duration) {
          _duration = duration;
          _timeRemaining = duration;
          _isRunning = true;
          _timer = Timer.periodic(Duration(seconds: 1), (timer) {
            if (_timeRemaining > 0) {
              _timeRemaining--;
              notifyListeners();
            } else {
              stopTimer();
            }
          });
          notifyListeners();
        }
      
        void stopTimer() {
          _isRunning = false;
          _timer.cancel();
          notifyListeners();
        }
      
        void updateTimeRemaining(int newTime) {
          _timeRemaining = newTime;
          notifyListeners();
        }
      }
      
      

      重要的是要注意,上面的代码只是一个框架,让您了解如何使用 Provider 包和 ChangeNotifier 类实现计时器,您可能需要调整它以满足您的特定要求。

      此外,您应该在 ChangeNotifier 的 dispose() 方法中处理 _timer.cancel() 以确保您没有运行不必要的计时器。

    【讨论】:

      猜你喜欢
      • 2021-08-12
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2021-10-01
      • 2022-11-12
      相关资源
      最近更新 更多