Flutter中支持暂停/继续的持久化计时器问题求助
解决方案:持久化完整计时器状态
要解决应用被杀后计时器归零的问题,同时支持暂停/继续功能,核心是完整持久化计时器的运行状态和关键时间数据,而非单一存储起始时间或当前值。以下是具体实现思路:
需要持久化的核心数据
用shared_preferences存储三组关键信息:
isRunning:布尔值,标记计时器当前处于运行中还是暂停状态elapsedMilliseconds:累计已完成的计时时长(毫秒),暂停状态下直接用该值恢复计时lastStartTime:最后一次启动计时的时间戳(毫秒),仅在运行状态下有效,用于重启后计算从上次启动到当前的流逝时间
具体实现逻辑
1. 应用启动时恢复状态
从shared_preferences读取保存的状态:
- 若为暂停状态:直接将
elapsedMilliseconds赋值给stop_watch_timer的初始值 - 若为运行状态:计算
当前时间戳 - lastStartTime,加上elapsedMilliseconds得到总时长,赋值给计时器后继续启动计时
2. 响应用户操作更新状态
- 点击开始/继续:记录当前时间戳为
lastStartTime,设置isRunning为true,持久化这两个值 - 点击暂停:读取
stop_watch_timer的当前值作为elapsedMilliseconds,设置isRunning为false,持久化这两个值
3. 后台自动保存状态
通过WidgetsBindingObserver监听应用生命周期,当应用进入后台(AppLifecycleState.paused)时自动保存当前状态:
- 运行中:计算当前累计时长,更新
elapsedMilliseconds为「截止上次启动前的累计时长」,同时更新lastStartTime为当前时间戳 - 暂停中:直接读取计时器当前值更新
elapsedMilliseconds
代码示例片段
import 'package:flutter/widgets.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stop_watch_timer/stop_watch_timer.dart'; class TimerManager with WidgetsBindingObserver { final StopWatchTimer stopWatchTimer = StopWatchTimer(); late SharedPreferences _prefs; bool _isRunning = false; int _elapsedMilliseconds = 0; int _lastStartTime = 0; Future<void> init() async { _prefs = await SharedPreferences.getInstance(); WidgetsBinding.instance.addObserver(this); // 读取本地存储的状态 _isRunning = _prefs.getBool('isRunning') ?? false; _elapsedMilliseconds = _prefs.getInt('elapsedMilliseconds') ?? 0; _lastStartTime = _prefs.getInt('lastStartTime') ?? 0; if (_isRunning) { final now = DateTime.now().millisecondsSinceEpoch; final totalElapsed = _elapsedMilliseconds + (now - _lastStartTime); stopWatchTimer.setPresetTime(mSec: totalElapsed); stopWatchTimer.onExecute.add(StopWatchExecute.start); _lastStartTime = now; await _saveState(); } else { stopWatchTimer.setPresetTime(mSec: _elapsedMilliseconds); } } Future<void> toggleTimer() async { if (_isRunning) { stopWatchTimer.onExecute.add(StopWatchExecute.stop); _isRunning = false; _elapsedMilliseconds = stopWatchTimer.rawTime.value; } else { stopWatchTimer.onExecute.add(StopWatchExecute.start); _isRunning = true; _lastStartTime = DateTime.now().millisecondsSinceEpoch; } await _saveState(); } Future<void> _saveState() async { await _prefs.setBool('isRunning', _isRunning); await _prefs.setInt('elapsedMilliseconds', _elapsedMilliseconds); await _prefs.setInt('lastStartTime', _lastStartTime); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.paused) { if (_isRunning) { final currentElapsed = stopWatchTimer.rawTime.value; _elapsedMilliseconds = currentElapsed - (DateTime.now().millisecondsSinceEpoch - _lastStartTime); _lastStartTime = DateTime.now().millisecondsSinceEpoch; } else { _elapsedMilliseconds = stopWatchTimer.rawTime.value; } _saveState(); } } void dispose() { WidgetsBinding.instance.removeObserver(this); stopWatchTimer.dispose(); } }
方案优势
- 兼容运行、暂停两种状态下的应用被杀场景,重启后完全恢复之前的计时状态
- 基于
shared_preferences实现,无需依赖复杂插件,性能稳定 - 通过生命周期监听自动保存状态,无需用户手动触发,体验流畅
内容的提问来源于stack exchange,提问作者Sparkringo
相关产品推荐
相关产品推荐

