每次设置状态时都会调用 Flutter 函数

Posted

技术标签:

【中文标题】每次设置状态时都会调用 Flutter 函数【英文标题】:Flutter function is getting called everytime state is set 【发布时间】:2021-10-20 19:34:00 【问题描述】:

我正在制作一个小游戏,用户需要使用网格视图中屏幕上提供的字符来猜测答案,我制作了包含来自答案的字符和一些随机字符的网格视图,以生成随机字符我制作了一个 randomString 函数并且在“Widget build(BuildContext context)”中被调用,但是每次我点击我的网格视图的按钮时,randomString 函数都会被调用并且单词会发生变化,所以我想要一种方式,这些字符不会每次都改变 -时间。

我也尝试过 Init,但它不适合我。


import 'package:flutter/material.dart';

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

  PuzzlePage(this.id, this.image1, this.image2, this.puzzleAnswer);

  State<StatefulWidget> createState()
  
    return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
  


//State<StatefulWidget> createState() 
//  return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);


class _PuzzlePageState extends State<PuzzlePage> 
  int? id;
  String? image1;
  String? image2;
  String? puzzleAnswer;

  _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
  void initState()
    super.initState();
  
  @override
  Widget build(BuildContext context) 
    // deciding keyboard size
    int? remainingLetters=26-(puzzleAnswer!.length);
    int extraSize=(remainingLetters/2).ceil();
    print(extraSize);
    print(puzzleAnswer!.length);
    int keyboardSize=puzzleAnswer!.length+extraSize;
    String randomCharactersString = RandomString(extraSize, puzzleAnswer!);
    String keyboardWords=randomCharactersString+puzzleAnswer!;
    print(randomCharactersString);
    List selection=[];

// const answer= "cde";
    //final id = ModalRoute.of(context)!.settings.arguments as Id ;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title:Text("Guess the answer"),
          centerTitle: true,
          automaticallyImplyLeading: true,
          leading: IconButton(icon:Icon(Icons.arrow_back),
            onPressed: () 
              Navigator.pop(context);
            ,
          ),
        ),
        body: Container(

          color: Colors.white54,
          child: Column(
            children: [
              SizedBox(
                height: 60,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                      height: 125,
                      width: 125,
                      child: Image(image: AssetImage("assets/images/$image1"))),
                  SizedBox(
                    width: 20,
                  ),
                  Text("$randomCharactersString"),
                  Container(
                      height: 125,
                      width: 125,
                      child: Image(image: AssetImage("assets/images/$image2"))),
                ], ),
              Column(
                children: [
                  Container(
                      height: 250,
                      padding: EdgeInsets.all(10),
                      alignment: Alignment.center,
                      child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        // childAspectRatio: 1,
                        crossAxisCount: 7,
                        crossAxisSpacing: 4,
                        mainAxisSpacing: 4,
                      ),
                          itemCount: puzzleAnswer!.length,
                          shrinkWrap: true,
                          itemBuilder: (context , index)
                          
                            return ElevatedButton(

                              style: ElevatedButton.styleFrom(
                                primary: Colors.purple,
                                textStyle: TextStyle(
                                    fontSize: 20,
                                    fontWeight: FontWeight.bold
                                ),
                              ),
                              onPressed: null,
                              child: Text("d"),
                            );
                          
                      )
                  ),
                ],
              ),
              Expanded(child:
              Container(
                  // height: 300,
                  padding: EdgeInsets.all(10),
                  alignment: Alignment.center,
                  child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    childAspectRatio: 1,
                    crossAxisCount: 7,
                    crossAxisSpacing: 4,
                    mainAxisSpacing: 4,
                  ),
                      itemCount: keyboardSize,
                      // shrinkWrap: true,
                      itemBuilder: (context , index)
                      
                      String singleWord=keyboardWords[index];
                      int x=keyboardWords.length;
                      return InkWell(
                      onTap:()
                      setState(()

                      if(selection.contains(keyboardWords[index]))
                      selection.remove(keyboardWords[index]);
                      else
                      selection.add(keyboardWords[index]);
                      );
                      ,
                      child: Container(
                      padding:EdgeInsets.all(10),
                      alignment:Alignment.center,
                      decoration:BoxDecoration(
                      // color:selection.contains(keyboardWords[index])?Colors.blueAccent:Colors.grey,
                      borderRadius:BorderRadius.circular(7)
                      ),
                      child:Text(keyboardWords[index],
                      style:TextStyle(color:Colors.black)
                      ),
                      ),
                      );

                        // return ElevatedButton(
                        //   style: ElevatedButton.styleFrom(
                        //     primary: Colors.purple,
                        //     // padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
                        //     textStyle: TextStyle(
                        //         fontSize: 20,
                        //         fontWeight: FontWeight.bold
                        //     ),
                        //   ),
                        //     onPressed: null,
                        //     child: Text("d"),
                        // );
                      
                  )
              ),
              ),
            ],
          ),
        ),

      ),
    );
  


 RandomString(int strlen,String puzzleAnswer)
  Random rnd = new Random();
  String result = "";
  const chars = "abcdefghijklmnopqrstuvwxyz";
  for (var i = 0; i < strlen; i++) 
    // if (!puzzleAnswer.contains(chars[i])) 
      result += chars[rnd.nextInt(chars.length)];
    // 
  
  return result;
```

【问题讨论】:

你想只加载一次吗? 【参考方案1】:

initState生成随机字符串并将结果放到_PuzzlePageState的类级别:

class _PuzzlePageState extends State<PuzzlePage> 
  ...
  late final String _randomCharactersString;

  _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);

  void initState()
    super.initState();
    // deciding keyboard size
    int? remainingLetters=26-(puzzleAnswer!.length);
    int extraSize=(remainingLetters/2).ceil();
    print(extraSize);
    print(puzzleAnswer!.length);
    int keyboardSize=puzzleAnswer!.length+extraSize;
    String randomCharactersString = RandomString(extraSize, puzzleAnswer!);
    ...
  

  ...

如果您需要更改某些操作的随机字符串,请创建一个函数来执行此操作并在需要时调用它。不要忘记致电setState() 以揭示变化:

class _PuzzlePageState extends State<PuzzlePage> 
  ...
  late String _randomCharactersString;

  _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);

  void initState()
    super.initState();
    _generateRandomString();
  

  ...

  void _someAction() 
    _generateRandomString();
    setState(() );
  

  void _generateRandomString() 
    // deciding keyboard size
    int? remainingLetters=26-(puzzleAnswer!.length);
    int extraSize=(remainingLetters/2).ceil();
    print(extraSize);
    print(puzzleAnswer!.length);
    int keyboardSize=puzzleAnswer!.length+extraSize;
    String randomCharactersString = RandomString(extraSize, puzzleAnswer!);
    ...
   

您可能需要为keyboardWordsselection 添加类级属性。

【讨论】:

以上是关于每次设置状态时都会调用 Flutter 函数的主要内容,如果未能解决你的问题,请参考以下文章

Angular2,为啥每次移动鼠标时都会调用函数

Flutter Page 每次在导航弹出时都会重新加载

功能性反应如何不重置状态?

React 上下文每次使用它时都会返回初始状态 - 尽管 setState

viewDidLoad 中的代码每次调用时都会运行

本地声明的 lua 函数是不是在每次传递时都会被解析?