Flutter中如何正确测量Widget挂载耗时?计时结果始终为0
解决Flutter页面Mount耗时计时始终为0的问题
问题根源
你每次调用StopWatchController()都会创建一个全新的实例:点击"next page"按钮时启动计时用的是一个实例,SecondPage的initState里停止计时用的是另一个完全独立的实例,两个实例的Stopwatch毫无关联,所以停止时拿到的必然是新计时器的初始时间。
修复方案
核心是让启动和停止计时操作共享同一个StopWatchController实例,具体修改如下:
- 在MyHomePage的State中初始化并持有一个固定的控制器实例
- 通过SecondPage的构造函数传递该实例
- 调整两处的计时调用,使用同一个实例操作
修改后的完整代码
import 'package:flutter/material.dart'; class StopWatchController { final stopWatch = Stopwatch(); void stopWatchHandler(String timer) { if (timer == "start") { stopWatch.start(); } else if (timer == "stop") { stopWatch.stop(); debugPrint(stopWatch.elapsed.toString()); } } } void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.blue), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { final String title; const MyHomePage({Key? key, required this.title}) : super(key: key); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // 持有同一个控制器实例 final _stopWatchController = StopWatchController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.title)), body: Center( child: ElevatedButton( child: const Text("next page"), onPressed: () { // 先启动计时再导航,保证起点准确 _stopWatchController.stopWatchHandler("start"); Navigator.of(context).push( MaterialPageRoute( // 传递控制器给SecondPage builder: (context) => SecondPage(controller: _stopWatchController), ), ); }, ), ), ); } } class SecondPage extends StatefulWidget { final StopWatchController controller; // 构造函数接收控制器 const SecondPage({Key? key, required this.controller}) : super(key: key); @override State<SecondPage> createState() => _SecondPageState(); } class _SecondPageState extends State<SecondPage> { @override void initState() { super.initState(); // 使用传递过来的同一个实例停止计时 widget.controller.stopWatchHandler("stop"); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: const Center(child: Text("")), ); } }
额外说明
- 调整了启动计时和导航的顺序:先启动计时器再执行导航,确保计时起点更准确
- 给
stopWatchHandler补充了返回值类型void,符合Dart类型规范 - 移除了
initState里多余的this.mounted判断,因为initState执行时widget已完成mount
内容的提问来源于stack exchange,提问作者FDjawid
相关产品推荐
相关产品推荐

