You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter使用Provider更新时间差失败,如何解决?

问题分析与解决方案

核心问题

你的代码存在两个关键问题导致组件无法接收更新:

  1. notifyListeners()调用不完整:仅在else分支触发通知,其他分支更新变量后未通知监听者
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 21:48:21