Flutter使用Provider更新时间差失败,如何解决?
问题分析与解决方案
核心问题
你的代码存在两个关键问题导致组件无法接收更新:
notifyListeners()调用不完整:仅在else分支触发通知,其他分支更新变量后未通知监听者- JWSModel实例不统一:组件内自己创建的实例与
context.watch获取的Provider实例是两个独立对象,Timer更新的实例和组件监听的实例不一致
步骤1:修复JWSModel的通知逻辑
将notifyListeners()移到方法最后,确保所有分支更新变量后都能通知监听者:
class JWSModel extends ChangeNotifier { String ketCounterShalat = ""; String diff = ""; void streamDifferentTime() { DateTime now = DateTime.now(); if (now.isBefore(dhuhrTime) && now.isAfter(_dhuha)) { ketCounterShalat = "Menuju dhuhur"; diff = now.difference(dhuhrTime).toString(); } else if (now.isBefore(asrTime) && now.isAfter(dhuhrTime)) { ketCounterShalat = "Menuju ashar"; diff = now.difference(asrTime).toString(); } else if (now.isBefore(maghribTime) && now.isAfter(asrTime)) { ketCounterShalat = "Menuju maghrib"; diff = now.difference(maghribTime).toString(); } else if (now.isBefore(ishaTime) && now.isAfter(maghribTime)) { ketCounterShalat = "Menuju isya"; diff = now.difference(ishaTime).toString(); } else if (now.isBefore(sunriseTime) && now.isAfter(fajrTime)) { diff = now.difference(sunriseTime).toString(); ketCounterShalat = "Menuju terbit"; } else if (now.isBefore(_dhuha) && now.isAfter(sunriseTime)) { diff = now.difference(_dhuha).toString(); ketCounterShalat = "Menuju dhuha"; } else { if (fajrTime.day == now.day) { diff = now.difference(fajrTime).toString(); } else if (fajrTime.day != now.day) { diff = now.difference(fajrTime.add(const Duration(days: 1))).toString(); } ketCounterShalat = "Menuju subuh"; } // 所有分支执行后统一通知监听者 notifyListeners(); } String get counterShalat => diff; String get ketCounter => ketCounterShalat; }
步骤2:统一JWSModel实例
2.1 在应用上层提供Provider
在main.dart中通过ChangeNotifierProvider全局提供JWSModel实例:
void main() { runApp( ChangeNotifierProvider( create: (context) => JWSModel(), child: const MyApp(), ), ); }
2.2 修改JWS组件代码
删除自己创建的实例,从Provider获取统一实例,并处理Timer的销毁:
class JWS extends StatefulWidget { const JWS({Key? key}) : super(key: key); @override State<JWS> createState() => _JWSState(); } class _JWSState extends State<JWS> { late Timer _timer; late JWSModel jws; Future<void> getJWS() async { jws.init(); // 执行祈祷时间初始化逻辑 } @override void initState() { super.initState(); // 从Provider获取统一实例 jws = context.read<JWSModel>(); getJWS(); // 使用统一实例触发更新 _timer = Timer.periodic(const Duration(seconds: 1), (timer) { jws.streamDifferentTime(); }); } @override void dispose() { // 销毁Timer避免内存泄漏 _timer.cancel(); super.dispose(); } @override Widget build(BuildContext context) { // 监听Provider中实例的变化 final state = context.watch<JWSModel>(); log(state.counterShalat); // 补充UI展示代码 return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(state.ketCounter, style: const TextStyle(fontSize: 20)), const SizedBox(height: 16), Text(state.counterShalat, style: const TextStyle(fontSize: 24)), ], ), ), ); } }
额外依赖说明
确保你的pubspec.yaml中已经添加Provider依赖:
dependencies: flutter: sdk: flutter provider: ^6.0.5 # 可替换为最新版本
内容的提问来源于stack exchange,提问作者Rian Pratama
相关产品推荐
相关产品推荐

