0

尝试在单击图标时弹出的 AlertDialog 框中流式传输数据时出现错误。我了解该问题涉及在不允许的情况下发生的流构建器构建,但我还没有找到解决此问题的方法。我的目标是能够单击一个图标并出现一个弹出框,显示一些流数据或带有取消按钮和清除数据按钮的最新实例。

enum WarningInfo { CANCEL, CLEAR }

class WarningStatus extends StatefulWidget {
  final ROSBridgeClient client;

  WarningStatus({Key key, this.client}) : super(key: key);

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

class WarningStatusState extends State<WarningStatus> {
  static const String _FAULT_TOPIC = '/active_faults';
  //color (gray) when icon has not been enabled
  Color _iconColor = Color(0xff4e4e4e);

  @override
  void initState() {
    super.initState();
  }

  Future<WarningInfo> _asyncWarningBox(BuildContext context) async {
    return showDialog<WarningInfo>(
      context: context,
      barrierDismissible:
          true, // user must tap button for close dialog if false!
      builder: (BuildContext context) {
        return AlertDialog(
          // content: StatefulBuilder(),
          title: Text('Robot Warnings'),
          // content: const Text('No warnings'),
          content: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
            return StreamBuilder(
                stream: widget.client.getTopicStream(_FAULT_TOPIC),
                builder: (context, snapshot) {
                  if (!snapshot.hasData) {
                    return Text('None');
                  }
                  return _buildFaultOutput(snapshot);
                });
          }),
          actions: <Widget>[
            FlatButton(
              child: const Text('CANCEL'),
              onPressed: () {
                Navigator.of(context).pop(WarningInfo.CANCEL);
              },
            ),
            FlatButton(
              child: const Text(
                'CLEAR WARNINGS',
                style: TextStyle(color: Colors.red),
              ),
              onPressed: () {
                // Navigator.of(context).pop(WarningInfo.CLEAR);
                _clearFaults();
              },
            )
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    widget.client.subscribe(_FAULT_TOPIC, 'rover_safety/FaultListMsg');

    return SizedBox(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          IconButton(
            icon: Icon(
              CustomIcons.attention,
              color: _iconColor,
            ),
            disabledColor: Color(0xff4e4e4e),
            iconSize: 80,
            tooltip: "Warnings",
            onPressed: () async {
              final WarningInfo action = await _asyncWarningBox(context);
              print("Confirm Action $action");
            },
            // onPressed: () {
            //   setState(() {
            //     _iconColor = Colors.yellow;
            //   });
            // },
          ),

          // Text("Fault Messages:"),
          // SizedBox(
          //   height: 10.0,
          // ),
          // StreamBuilder(
          //   stream: widget.client.getTopicStream(_FAULT_TOPIC),
          //   builder: (context, snapshot) {
          //     if (!snapshot.hasData) {
          //       return CircularProgressIndicator();
          //     }
          //     return _buildFaultOutput(snapshot);
          //   },
          // ),
          // SizedBox(
          //   height: 10.0,
          // ),
          // ButtonBar(
          //   mainAxisSize: MainAxisSize.min,
          //   children: <Widget>[
          //     RaisedButton(
          //       child: const Text("Clear Faults"),
          //       onPressed: _clearFaults,
          //     ),
          //   ],
          // )
        ],
      ),
    );
  }

  Widget _buildFaultOutput(snapshot) {
    setState(() {
      _iconColor = Colors.blue;
    });
    var msg = snapshot.data;
    // print(payload);

    var faultList = msg["fault_list"];

    print("Number of faults: ${faultList.length}");

    // if (faultListLength>0){
    //   var faults = faultList[0];
    //   var motorCurrent = faults["fault"];
    //   var severity = faults["severity"];
    //   print(faults);
    //   return Text("Number of Faults: $faultListLength\n$motorCurrent\nseverity: $severity");
    // }
    // else{
    //   return Text("No faults");
    //   }

    if (faultList.length == 0) {
      return Text("No faults");
    } else {
      for (var i = 0; i < faultList.length; i++) {
        var faults = faultList[i];
        var motorCurrent = faults["fault"];
        var severity = faults["severity"];
        print(faults);
        print(i);
        return Text(
            "Number of Faults: ${faultList.length}\n$motorCurrent\nseverity: $severity");
      }
    }
  }

  void _clearFaults() {
    widget.client.publish('/clear_faults', 'std_msgs/Empty');
  }

  @override
  void dispose() {
    super.dispose();
  }
}

错误:

I/flutter ( 1382): Another exception was thrown: setState() or markNeedsBuild() called during build.

错误:

I/flutter ( 2967): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 2967): The following assertion was thrown building StreamBuilder<dynamic>(dirty, state:
I/flutter ( 2967): _StreamBuilderBaseState<dynamic, AsyncSnapshot<dynamic>>#dc80d):
I/flutter ( 2967): setState() or markNeedsBuild() called during build.
I/flutter ( 2967): This WarningStatus widget cannot be marked as needing to build because the framework is already in
I/flutter ( 2967): the process of building widgets.  A widget can be marked as needing to be built during the build
I/flutter ( 2967): phase only if one of its ancestors is currently building. This exception is allowed because the
I/flutter ( 2967): framework builds parent widgets before children, which means a dirty descendant will always be
I/flutter ( 2967): built. Otherwise, the framework might not visit this widget during this build phase.
I/flutter ( 2967): The widget on which setState() or markNeedsBuild() was called was:
I/flutter ( 2967):   WarningStatus
I/flutter ( 2967): The widget which was currently being built when the offending call was made was:
I/flutter ( 2967):   StreamBuilder<dynamic>
I/flutter ( 2967): 
I/flutter ( 2967): The relevant error-causing widget was:
I/flutter ( 2967):   StreamBuilder<dynamic> file:///home/megan/rr_app/lib/widgets/warnings.dart:45:20
I/flutter ( 2967): 
I/flutter ( 2967): When the exception was thrown, this was the stack:
I/flutter ( 2967): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4167:11)
I/flutter ( 2967): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4182:6)
I/flutter ( 2967): #2      State.setState (package:flutter/src/widgets/framework.dart:1253:14)
I/flutter ( 2967): #3      WarningStatusState._buildFaultOutput (package:rrapp/widgets/warnings.dart:135:5)
I/flutter ( 2967): #4      WarningStatusState._asyncWarningBox.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:rrapp/widgets/warnings.dart:51:26)
I/flutter ( 2967): #5      StreamBuilder.build (package:flutter/src/widgets/async.dart:509:81)
I/flutter ( 2967): #6      _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:127:48)
I/flutter ( 2967): #7      StatefulElement.build (package:flutter/src/widgets/framework.dart:4619:28)
I/flutter ( 2967): #8      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
I/flutter ( 2967): #9      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:11)
I/flutter ( 2967): #10     Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
I/flutter ( 2967): #11     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2627:33)
I/flutter ( 2967): #12     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:883:20)
I/flutter ( 2967): #13     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:284:5)
I/flutter ( 2967): #14     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1108:15)
I/flutter ( 2967): #15     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1047:9)
I/flutter ( 2967): #16     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:963:5)
I/flutter ( 2967): #20     _invoke (dart:ui/hooks.dart:261:10)
I/flutter ( 2967): #21     _drawFrame (dart:ui/hooks.dart:219:3)
I/flutter ( 2967): (elided 3 frames from dart:async)
I/flutter ( 2967): 
I/flutter ( 2967): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 2967): Another exception was thrown: setState() or markNeedsBuild() called during build.
4

1 回答 1

0

您在错误的位置调用 setState,....

只需从中删除 setStateWidget _buildFaultOutput(snapshot)并将其简单地设置为_iconColor = Colors.blue.

最后补充一下

setState(() => _iconColor = Colors.blue );在你做任何你AlertDialog actions's FlatButton 之后Navigator.pop(context)....

于 2020-07-27T19:20:34.443 回答