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

Flutter中多个Stateful Widget实例点击后无法同步更新的问题

问题根源

每个Die组件都维护了独立的dieNumbers状态副本,点击其中一个骰子时,只有该组件的setState()会触发自身重建,另一个骰子的状态还是它自己的旧数据,因此不会同步更新。

解决方案:状态提升

把共享的骰子状态(数字)移到父组件DicePage中统一管理,让Die组件仅负责展示和触发事件,不再维护自身状态。

修改后的完整代码

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.red,
        appBar: AppBar(
          title: const Text('Dicee'),
          backgroundColor: Colors.red,
        ),
        body: const DicePage(),
      ),
    ),
  );
}

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

  @override
  State<DicePage> createState() => _DicePageState();
}

class _DicePageState extends State<DicePage> {
  final Map<DiePosition, int> dieNumbers = {
    DiePosition.Left: 1,
    DiePosition.Right: 1
  };
  final Random rd = Random();

  void rollBothDice() {
    setState(() {
      dieNumbers[DiePosition.Left] = rd.nextInt(6) + 1;
      dieNumbers[DiePosition.Right] = rd.nextInt(6) + 1;
    });
    print('LB: ${dieNumbers[DiePosition.Left]} RB: ${dieNumbers[DiePosition.Right]}');
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        children: [
          Die(
            number: dieNumbers[DiePosition.Left]!,
            onTap: rollBothDice,
          ),
          Die(
            number: dieNumbers[DiePosition.Right]!,
            onTap: rollBothDice,
          ),
        ],
      ),
    );
  }
}

enum DiePosition {
  Right,
  Left,
}

class Die extends StatelessWidget {
  final int number;
  final VoidCallback onTap;

  const Die({super.key, required this.number, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: TextButton(
        child: Image.asset('images/dice$number.png'),
        onPressed: onTap,
      ),
    );
  }
}

关键改动说明

  1. 父组件统一管理状态:将dieNumbers、Random实例和刷新逻辑rollBothDice移到_DicePageState中,父组件的setState()会触发所有子组件重建
  2. Die改为无状态组件:仅接收要展示的数字和点击回调,不再维护自身状态,变成纯展示组件
  3. 同步刷新逻辑:点击任意骰子都会调用父组件的rollBothDice,触发父组件状态更新,两个骰子会同步刷新

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 11:07:31