A
A
Alexey Gus2021-08-25 15:06:22
Dart
Alexey Gus, 2021-08-25 15:06:22

Flutter how to make a stopwatch so that it works in the background when the application switches to another screen?

Good day to all!
The essence of the question is, there is a screen with buttons (let's say there are 2 of them), when pressed, the stopwatch starts, but the problem is that you need to keep the stopwatch running in the background when the user switches to another screen of the application and (or) minimizes it, and when opens the screen with buttons to display the stopwatch again with the current value since the start.

I have implemented the stopwatch so far

StopWatchTimer _stopWatchTimer = StopWatchTimer(
      mode: StopWatchMode.countUp,
      onChangeRawSecond: (value) => print('presetMillisecond:  $value'),
      onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
    );

and took the value from it like this
StreamBuilder<int>(
      stream: _stopWatchTimer.secondTime,
      initialData: _stopWatchTimer.secondTime.value,
      builder: (context, snap) {
        var value = snap.data;
        return StreamBuilder<int>(
      stream: _stopWatchTimer.secondTime,
      initialData: _stopWatchTimer.secondTime.value,
      builder: (context, snap) {
        var value = snap.data;
        return Card(
              child: Padding(
              padding: EdgeInsets.all(10),
              child: InkWell(
                onTap: () {
                  selectedButton = key;
                        if (!_stopWatchTimer.isRunning) {
                          _stopWatchTimer.onExecute.add(StopWatchExecute.reset);
                          _stopWatchTimer.onExecute.add(StopWatchExecute.start);
                        } else {
                          selectedButton = '';
                          _stopWatchTimer.onExecute.add(StopWatchExecute.reset);
                          _stopWatchTimer.onExecute.add(StopWatchExecute.stop);
                        }
                  }
                },
                child: 
                       Text(   '${value.toString()}',
                                              style: GoogleFonts.roboto(
                                                  textStyle: TextStyle(
                                                    color: Color.fromRGBO(6, 8, 15, 1),
                                                    fontWeight: FontWeight.w700,
                                                    fontSize: 14.sp,
                                                  )),
                                            )        
              ),
            ));
      },
    );,


I read that there is a variant to do this through AndroidAlarmManager, but it seems like it stops working after half an hour in the background.
who thinks what? how to do it better ?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexey Gus, 2021-08-26
@Holyboom

In short, I filed a global service with a timer and separately simply screwed AndroidAlarmManager so that it monitors the opening and closing of the application.
So far it looks like this
Service itself

class TimerService extends ChangeNotifier {
      Stopwatch _watch = Stopwatch();
      var _timer;
 
      Duration get currentDuration => _currentDuration;
      Duration _currentDuration = Duration.zero;
     bool get isRunning => _timer != null;

     TimerService() {
        _watch = Stopwatch();
     }

    String get getTime => getDisplayTime(_currentDuration.inMilliseconds);

     static String getDisplayTime(){
     //перевод человеко читаемый вид(если кому надо пишите скину код) 
     }

    void _onTick(Timer timer) {
      _currentDuration = _watch.elapsed;
      print(_currentDuration);
      // notify all listening widgets
      notifyListeners();
    }

    void start() {
       if (_timer != null) return;
       _timer = null;
       _timer = Timer.periodic(Duration(seconds: 1), _onTick);
       _watch.start();
       notifyListeners();
    }

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

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

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

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

and listener
AnimatedBuilder(
                                animation: globalsVars.timerServ,
                                builder: (context, child) {
                                  return Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: <Widget>[
                                  Container(
                                      padding: EdgeInsets.only(top: 5 , left: 12),
                                      decoration: (selectedButton == key)
                                          ? BoxDecoration(
                                        border: Border.all(
                                          color: Colors.white10,
                                          width: 2,
                                        ),
                                        borderRadius: BorderRadius.circular(5),
                                      )
                                          : null,
                                      child:  Text(
                                        '${globalsVars.timerServ.getTime}',
                                        style: GoogleFonts.roboto(
                                            textStyle: TextStyle(
                                              color: Colors.red,
                                              fontWeight: FontWeight.w700,
                                              fontSize: 16.sp,
                                            )),
                                      ))
                                    ],
                                  );
                                },
                              ),

So far, I have not come up with a more elegant solution ... so if anyone has thoughts, I will be glad to hear your opinion

V
Vadim Popov, 2021-09-15
@vadimpopov94

It could have been done much easier and without being tied to the platform (in your case, there is a binding to android).
At the start time, I would make an entry with the current date and time in shared_preferences
Then just calculate the difference between the current date and the one that is written to the storage. With difference

final startTime = DateTime(1967, 10, 12); //Тут будет значение из хранилища
final now = DateTime.now();
final difference = startTime.difference(birthday).inSeconds;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question