@Holyboom
junior fullstack

Flutter как сделать секундомер так чтобы он работал в фоне, когда приложение переключилось на другой экран?

Всем доброго времени суток!
Суть вопроса в чем , есть экран с кнопками(допустим их 2) , при нажатии на которые запускается секундомер , но проблема в том что нужно сохранить работу секундомера в фоне, когда пользователь переключиться на другой экран приложения и(или) свернет его, а когда откроет экран с кнопками снова отобразить секундомер с актуальным значением с момента старта.

секундомер я пока реализовал так
StopWatchTimer _stopWatchTimer = StopWatchTimer(
      mode: StopWatchMode.countUp,
      onChangeRawSecond: (value) => print('presetMillisecond:  $value'),
      onChangeRawMinute: (value) => print('onChangeRawMinute $value'),
    );

и брал из него значение так
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,
                                                  )),
                                            )        
              ),
            ));
      },
    );,


Читал что есть варик сделать так через AndroidAlarmManager , но вроде как он перестает работать через пол часа в фоне .
кто что думает ? как лучше сделать ?
  • Вопрос задан
  • 644 просмотра
Решения вопроса 1
@Holyboom Автор вопроса
junior fullstack
Короче запилил глобальный сервис с таймером и отдельно просто прикрутил AndroidAlarmManager чтобы он следил за открытием закрытием приложения .

Пока что выглядит так
Сам сервис

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


и слушатель

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,
                                            )),
                                      ))
                                    ],
                                  );
                                },
                              ),


Пока что более элегантного решения не придумал ... так что если у кого есть мысли буду рад вашему мнению
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
vadimpopov94
@vadimpopov94
Dev
Можно было сделать гораздо проще и без привязки к платформе (в твоём случае есть привязка к андроиду).

В момент старта я бы сделал запись с текущей датой и временем в shared_preferences

Затем просто высчитывать разницу между текущей датой и той что записано в хранилище. С помощью difference
final startTime = DateTime(1967, 10, 12); //Тут будет значение из хранилища
final now = DateTime.now();
final difference = startTime.difference(birthday).inSeconds;
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы