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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:35:18