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

Flutter setState触发build重复调用随机字符生成函数,initState无效怎么解决?

问题修复方案

根因说明

  • 所有可变状态、随机生成逻辑都写在build方法内,每次点击按钮调用setState都会触发页面重绘,build方法会重新执行一遍,导致随机字符重新生成、用户选择的内容也被清空。
  • 无需手动给State构造函数传递参数,State实例可直接通过widget.属性名访问父组件PuzzlePage的所有属性,手动传参反而容易出现数据不同步的问题。

修改方法

  1. 将需要持久保存的变量提升为_PuzzlePageState的成员变量
  2. 把随机字符生成、键盘参数计算的逻辑全部迁移到initState中,该方法只会在页面初始化时执行一次,不会随重绘重复调用

完整修改后代码

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

class PuzzlePage extends StatefulWidget {
  final int? id;
  final String? image1;
  final String? image2;
  final String? puzzleAnswer;

  const PuzzlePage(this.id, this.image1, this.image2, this.puzzleAnswer, {super.key});

  @override
  State<StatefulWidget> createState() => _PuzzlePageState();
}

class _PuzzlePageState extends State<PuzzlePage> {
  late int extraSize;
  late int keyboardSize;
  late String randomCharactersString;
  late String keyboardWords;
  late List selection;

  @override
  void initState(){
    super.initState();
    // 所有初始化逻辑移到这里,仅执行一次
    int remainingLetters = 26 - (widget.puzzleAnswer!.length);
    extraSize = (remainingLetters/2).ceil();
    keyboardSize = widget.puzzleAnswer!.length + extraSize;
    randomCharactersString = RandomString(extraSize, widget.puzzleAnswer!);
    keyboardWords = randomCharactersString + widget.puzzleAnswer!;
    selection = [];
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title:const Text("猜答案"),
          centerTitle: true,
          automaticallyImplyLeading: true,
          leading: IconButton(icon:const Icon(Icons.arrow_back),
            onPressed: () {
              Navigator.pop(context);
            },
          ),
        ),
        body: Container(
          color: Colors.white54,
          child: Column(
            children: [
              const SizedBox(
                height: 60,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                      height: 125,
                      width: 125,
                      child: Image(image: AssetImage("assets/images/${widget.image1}"))),
                  const SizedBox(
                    width: 20,
                  ),
                  Text(randomCharactersString),
                  Container(
                      height: 125,
                      width: 125,
                      child: Image(image: AssetImage("assets/images/${widget.image2}"))),
                ], ),
              Column(
                children: [
                  Container(
                      height: 250,
                      padding: const EdgeInsets.all(10),
                      alignment: Alignment.center,
                      child: GridView.builder(gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 7,
                        crossAxisSpacing: 4,
                        mainAxisSpacing: 4,
                      ),
                          itemCount: widget.puzzleAnswer!.length,
                          shrinkWrap: true,
                          itemBuilder: (context , index)
                          {
                            return ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.purple,
                                textStyle: const TextStyle(
                                    fontSize: 20,
                                    fontWeight: FontWeight.bold
                                ),
                              ),
                              onPressed: null,
                              child: const Text("d"),
                            );
                          }
                      )
                  ),
                ],
              ),
              Expanded(child:
              Container(
                  padding: const EdgeInsets.all(10),
                  alignment: Alignment.center,
                  child: GridView.builder(gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                    childAspectRatio: 1,
                    crossAxisCount: 7,
                    crossAxisSpacing: 4,
                    mainAxisSpacing: 4,
                  ),
                      itemCount: keyboardSize,
                      itemBuilder: (context , index)
                      {
                        return InkWell(
                          onTap:(){
                            setState((){
                              if(selection.contains(keyboardWords[index])) {
                                selection.remove(keyboardWords[index]);
                              } else {
                                selection.add(keyboardWords[index]);
                              }
                            });
                          },
                          child: Container(
                            padding:const EdgeInsets.all(10),
                            alignment:Alignment.center,
                            decoration:BoxDecoration(
                                borderRadius:BorderRadius.circular(7)
                            ),
                            child:Text(keyboardWords[index],
                                style:const TextStyle(color:Colors.black)
                            ),
                          ),
                        );
                      }
                  )
              ),
              ),
            ],
          ),
        ),

      ),
    );
  }
}

String RandomString(int strlen,String puzzleAnswer){
  Random rnd = Random();
  String result = "";
  const chars = "abcdefghijklmnopqrstuvwxyz";
  for (var i = 0; i < strlen; i++) {
    result += chars[rnd.nextInt(chars.length)];
  }
  return result;
}

额外优化建议

  • 可修改RandomString函数逻辑,过滤掉已经存在于答案中的字符,避免生成重复字符影响游戏体验
  • 可将生成后的keyboardWords随机打乱顺序,避免答案字符连续排列降低游戏难度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 12:42:02