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

如何在Flutter中从一个Stateful Widget更新另一个Stateful Widget?

解决方案:使用Flutter状态提升(State Lifting)

不用全局变量或第三方状态管理库,最符合Flutter标准特性的方案是状态提升——把共享状态放到组件树中最近的共同父组件里,通过回调函数传递状态更新,再将状态向下传递给需要的子组件。

以下是修改后的完整代码:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Circuit Cellar!',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class _MyHomePageState extends State<MyHomePage> {
  // 共享状态移至父组件State中
  final List<String> taskLabels = [
    'Embedded in Thin Slices',
    'Technology Features',
    'Datasheets',
  ];
  int _selectedTaskCount = 0;

  // 计算进度百分比
  double get _progressPercentage => _selectedTaskCount / taskLabels.length;

  // 子组件Checkbox点击回调
  void _onTaskToggled(bool isSelected) {
    setState(() {
      if (isSelected) {
        _selectedTaskCount++;
      } else {
        _selectedTaskCount--;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Circuit Cellar Reading Planner!'),
      ),
      body: Column(
        children: [
          // 向Progress组件传递进度值
          Progress(percent: _progressPercentage),
          // 向TaskList传递任务列表和回调
          TaskList(
            taskLabels: taskLabels,
            onTaskToggled: _onTaskToggled,
          ),
        ],
      ),
    );
  }
}

class Progress extends StatelessWidget {
  final double percent;

  // 接收父组件传递的进度值
  const Progress({super.key, required this.percent});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Reading Progress:'),
        LinearProgressIndicator(value: percent),
      ],
    );
  }
}

class TaskList extends StatelessWidget {
  final List<String> taskLabels;
  final Function(bool) onTaskToggled;

  const TaskList({
    super.key,
    required this.taskLabels,
    required this.onTaskToggled,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: taskLabels
          .map((label) => TaskItem(
                label: label,
                onToggle: onTaskToggled,
              ))
          .toList(),
    );
  }
}

class TaskItem extends StatefulWidget {
  final String label;
  final Function(bool) onToggle;

  const TaskItem({
    super.key,
    required this.label,
    required this.onToggle,
  });

  @override
  State<TaskItem> createState() => _TaskItemState();
}

class _TaskItemState extends State<TaskItem> {
  bool _isChecked = false;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Checkbox(
          onChanged: (newValue) {
            setState(() {
              _isChecked = newValue ?? false;
              // 调用父组件回调,通知状态更新
              widget.onToggle(_isChecked);
            });
          },
          value: _isChecked,
        ),
        Text(widget.label),
      ],
    );
  }
}

关键改动说明:

  • 状态集中管理:把选中任务数量、任务标签列表移到_MyHomePageState中,消除全局变量,让状态在可控范围内流转。
  • 组件职责拆分:
    • Progress改为无状态组件,直接接收父组件传递的进度值完成渲染。
    • TaskList负责生成任务项,将父组件的回调传递给每个TaskItem。
    • TaskItem仅维护自身选中状态,点击时通过回调通知父组件更新全局计数。
  • 回调传递状态:通过onTaskToggled回调将子组件的交互事件传递给父组件,触发父组件setState,自动更新所有依赖该状态的子组件(包括Progress)。
  • 修正原代码错误:修复了原代码中TasbkItem的拼写错误,统一为TaskItem。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:57:20