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

Flutter withClock模拟时钟调用WidgetsFlutterBinding.ensureInitialized()时行为异常

Flutter withClock模拟时钟失效问题:原因与解决办法

问题本质

先调用WidgetsFlutterBinding.ensureInitialized()再用withClock包裹runApp时,会出现build方法内能拿到模拟时间,但build外的方法(比如按钮点击回调)只能拿到真实时间的情况。核心原因是:

  • WidgetsFlutterBinding.ensureInitialized()会提前启动Flutter核心绑定框架,包括初始化事件循环、后台线程等组件,这些组件的调用栈不在withClock的作用域内。
  • runApp在withClock内执行,build方法由Flutter框架在withClock作用域调度,所以能正常获取模拟时间;但按钮点击这类交互事件由Flutter事件循环线程处理,该线程调用栈不受外层withClock影响,因此clock.now()会返回真实时间。

解决办法

把WidgetsFlutterBinding.ensureInitialized()移到withClock的回调内部,让Flutter绑定的整个初始化过程都处于模拟时钟的作用域中,这样所有后续框架任务(包括事件回调)都会继承这个模拟环境:

修改后的main函数代码:

void main() {
  withClock(Clock.fixed(DateTime(1990)), () {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(const MyApp());
  });
}

验证效果

修改后,无论是build方法里的clock.now(),还是_printClockNow按钮回调中的打印,都会返回预设的1990年模拟时间,所有地方时钟表现一致,测试可正常进行。

完整修改后代码

import 'package:clock/clock.dart';
import 'package:flutter/material.dart';

void main() {
  withClock(Clock.fixed(DateTime(1990)), () {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(const MyApp());
  });
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _printClockNow() {
    print('_printClockNow is: ${clock.now()}'); // 现在会打印模拟的1990年时间
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    print('build clock.now() is: ${clock.now()}'); // 打印模拟时间
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const <Widget>[Dummy()],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _printClockNow,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Dummy extends StatelessWidget {
  const Dummy({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text('t: ${clock.now()}');
  }
}

内容的提问来源于stack exchange,提问作者Maciej Pszczolinski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:34:43