从 flutter 的子事件中调用 setState?

Calling setState from a child event in flutter?

每当应用程序从串行设备(使用 usb_serial 包)接收数据时,我需要重新绘制 UI。

TextEditingController cntrl = TextEditingController();
...
ListView(
children:[
                     TextButton(
                        onPressed: () async {
                          port = await _deviceList[0].create();
                          bool? openResult = await port?.open();
                          if (!openResult!) {
                            SmartDialog.showToast("Failed to connect!");
                            return;
                          }
                          port?.setPortParameters(
                            globals.baudRate,
                            globals.dataBits,
                            globals.stopBits,
                            globals.parity,
                          );
                          SmartDialog.showToast("Connected!");
                          port?.inputStream?.listen((Uint8List event) {
                            setState(() {
                              _cntrl.text=utf8.decode(event);
                            });
                          });
                        },
                        child: const Text("Start"),
                        style: startButtonStyle,
                      ),
   TextField(
     controller: _cntrl,
   ),
],
)

但是 UI 永远不会重绘。如果我必须从子事件调用 setState() 但找不到任何答案,我在网上搜索了很多关于应该做什么的信息。可能的解决方案是什么?

编辑: 显然这只是一些奇怪的错误,我将相同的代码复制到一个新项目中,它开始运行得很好。

一个简单的方法是传递一个函数给child,例如:

class MyChildWidget extends StatelessWidget {
  final VoidCallback onRefresh; // The callback that will be called to refresh parent state

  const MyChildWidget({Key? key, required this.onRefresh}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => onRefresh(), // Call the callback when button is tapped
      child: Text('Refresh Parent'),
    );
  }
}

现在使用MyChildWidget时,可以传入onRefresh参数,让它在parent中执行setState,例如:

MyChildWidget(
  onRefresh: () => setState(() {}),
);

这将是进行一些简单状态管理的简单方法。当事情变得太复杂时,您可以研究一些更高级的状态管理解决方案,例如 StreamBuilderprovider 包。


更新:

根据你更新的问题,问题不在 set state。也许您的 input stream 没有发出事件。您可以尝试添加 print 语句来检查流是否正常工作。

试试这个更短的代码来测试“将状态设置为 TextField”的概念,您应该会看到它按预期工作:

final _controller = TextEditingController();

// ...

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    TextButton(
      onPressed: () => setState(() {
        _controller.text = 'Hello World';
      }),
      child: const Text('Set text'),
    ),
    TextField(
      controller: _controller,
    ),
  ],
)