如何将StatefulWidget倒计时时钟迁移至ChangeNotifier实现跨页共享
完整倒计时迁移到ChangeNotifier方案
1. 实现CountdownTimers ChangeNotifier
把原来StatefulWidget里的状态、定时器逻辑全部迁移到这里,用notifyListeners()替代setState()通知UI刷新:
import 'dart:async'; import 'package:flutter/foundation.dart'; class CountdownTimers extends ChangeNotifier { // 初始倒计时时长,可按需修改 Duration _remainingTime = const Duration(hours: 1); Timer? _timer; bool _isRunning = false; // 对外暴露状态 getter Duration get remainingTime => _remainingTime; bool get isRunning => _isRunning; // 启动倒计时 void startTimer() { if (_isRunning) return; _isRunning = true; _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_remainingTime.inSeconds <= 0) { stopTimer(); return; } _remainingTime -= const Duration(seconds: 1); notifyListeners(); // 通知UI刷新 }); notifyListeners(); } // 停止倒计时 void stopTimer() { _isRunning = false; _timer?.cancel(); _timer = null; notifyListeners(); } // 一键切换启停 void toggleTimer() { _isRunning ? stopTimer() : startTimer(); } // 重置倒计时(可选功能,按需添加) void resetTimer(Duration newTime) { stopTimer(); _remainingTime = newTime; notifyListeners(); } // 销毁时清理定时器,避免内存泄漏 @override void dispose() { _timer?.cancel(); super.dispose(); } }
2. 重构UI组件(改为无状态Widget)
UI层只负责展示状态和触发方法,通过Consumer监听ChangeNotifier的状态变化:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class CountdownPage extends StatelessWidget { const CountdownPage({super.key}); // 复用你已实现的TimeDisplay组件 Widget TimeDisplay(Duration remainingTime) { String hours = remainingTime.inHours.toString().padLeft(2, '0'); String minutes = (remainingTime.inMinutes % 60).toString().padLeft(2, '0'); String seconds = (remainingTime.inSeconds % 60).toString().padLeft(2, '0'); return Text( '$hours:$minutes:$seconds', style: const TextStyle(fontSize: 48, fontWeight: FontWeight.bold), ); } @override Widget build(BuildContext context) { return Scaffold( body: Consumer<CountdownTimers>( builder: (context, timerModel, child) { return InkWell( onTap: timerModel.toggleTimer, // 调用ChangeNotifier的切换方法 child: Center(child: TimeDisplay(timerModel.remainingTime)), ); }, ), ); } }
3. 全局注入状态(实现多页面共享)
在应用入口用ChangeNotifierProvider包裹,确保所有子页面都能访问到同一个CountdownTimers实例:
void main() { runApp( ChangeNotifierProvider( create: (context) => CountdownTimers(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: const CountdownPage(), // 其他页面只需通过Provider.of<CountdownTimers>(context)即可获取共享状态 ); } }
核心注意点
- 所有状态逻辑(时间更新、定时器管理)都放在ChangeNotifier中,UI层只做纯展示
- 用
notifyListeners()替代setState(),每次状态变更后调用该方法触发UI刷新 - 多个页面共享状态时,直接在对应页面通过
Consumer或Provider.of<CountdownTimers>(context)获取实例即可
内容的提问来源于stack exchange,提问作者Nomad09
相关产品推荐
相关产品推荐

