dart 无需按下按钮即可自动设置按钮状态

yfwxisqw  于 2023-01-06  发布在  其他
关注(0)|答案(3)|浏览(174)

我有一个国家管理问题,我无法摆脱,我想接触你。
基本上,我用按钮激活一个游戏,然后向uC发送一个字符串。uC完成它的工作,并向Flutter发送一个响应,包括gameFinished=true(这很有效)。
现在我想在不按下按钮的情况下将按钮的状态重置为初始状态。以下是我尝试过但没有成功的一些操作。

@override
  void initState() {
    super.initState();
    setState(() {
      gameAktivated = false;
      gameStarted = false;
    });
  }
void asyncSetState() async {
    setState(() async {
      gameAktivated = false;
      gameStarted = false;
    });
  }

当按下按钮并将数据发送到uC时,我将样式从“开始”更改为“停止”。(Works)编辑:Ofc我有第二个按钮可以触发gameAktivated=true:)

ElevatedButton(
 onPressed: () {
  if (gameAktivated) {
   setState(() {
   gameStarted = !gameStarted;
  });
 if (gameStarted) {
  //Send Data to uC
 } else if (!gameStarted) {
  //Send Data to uC
 }
}
},
                    
child:
!gameStarted ? const Text('Start') : const Text('Stop'),
),

按钮显示现在停止。下面我从uC接收一个字符串,我jsonEncode和我收到gameFinished=true。(工程)

Container(
 child: streamInit
 ? StreamBuilder<List<int>>(
  stream: stream,
  builder: (BuildContext context,
  AsyncSnapshot<List<int>> snapshot) {
   if (snapshot.hasError) {
    return Text('Error: ${snapshot.error}');
   }
   if (snapshot.connectionState ==ConnectionState.active) {
    // getting data from Bluetooth
    var currentValue =const BluetoothConnection().dataParser(snapshot.data);
    config.jsonDeserializeGameFinished(currentValue);
    if(config.gameFinished){
     setState(() {
      gameAktivated = false;
      gameStarted = false;
     });
     asyncSetState();//Tested both methods seperate!
    }
    return Column(
     children: [
      Text(config.time.toString()),
     ],
    );
   } else {
    return const Text(
    'Check the stream',
    textAlign: TextAlign.center,
   );
  }
},
 ): const Text("NaN",textAlign: TextAlign.center,),
),

当我尝试像上面的代码那样重置状态时,会出现此错误:

调用setState Async对我也不起作用。我在哪里以及如何根据uC的响应设置状态?不使用Provider Lib是否可行?提前感谢Manuel。

qlfbtfca

qlfbtfca1#

实际上,这个错误不是关于改变按钮的状态。当它还在构建小部件树时,更新小部件状态是一个常见的错误。
在StreamBuilder中,您尝试在创建UI之前更新状态,这会引发此问题。

if(config.gameFinished){
     setState(() {
      gameAktivated = false;
      gameStarted = false;
     });

这将中断StreamBuilder的构建过程,因为它将开始更新整个页面。您需要将其移出StreamBuilder的构建器方法。
要做到这一点,只需将您的流转换为广播,这将允许您多次收听您的流。

var controller = StreamController<String>.broadcast();

然后在页面的initState中,您可以设置一个侦听器方法来侦听更改,如下所示

stream.listen((val) => setState((){
      number = val;
    }));

您可以在这里更改状态值,因为从这里起,它不会中断小部件树的构建周期。
有关更多详细信息,请参见我创建的https://dartpad.dev/?id=a7986c44180ef0cb6555405ec25b482d示例

bis0qfac

bis0qfac2#

如果要在调用build方法后立即调用setState(),应用途:

WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
     // this method gets called once directly after the previous setState() finishes.
 });
toiithl6

toiithl63#

回答我自己的问题:在initState()中添加了以下内容:

stream.listen((event) {
 String valueJSON = const BluetoothConnection().dataParser(event);
 config.jsonDeserializeGameFinished(valueJSON);
 if (config.gameFinished) {
  setState(() {
   gameAktivated = false;
   gameStarted = false;
  });
 }
});

上面的代码监听流,UTF-8解码和JSON解码数据,然后你可以访问变量来设置状态。

相关问题