【问题标题】:Change Variable values in Flutter在 Flutter 中更改变量值
【发布时间】:2019-03-21 12:57:00
【问题描述】:

我正在尝试更改 Flutter 中不同方法中的一些变量,但值没有改变。

一个例子是这样的:

enum UserPlaceStatusType { NONE, GOING, THERE, OUT, CANCELLED }

class PlaceCardState extends State<PlaceCard> {
    UserPlaceStatusType _isOtherPlaceActive = UserPlaceStatusType.NONE;

    Widget build(BuildContext context) {
    return Card(
        child: Scaffold(
            body: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: this._getBody(),
            ),
            bottomNavigationBar: this._getBottomNavigationBar()));
    }

    List<Widget> _getBody() {
        return [
            Expanded(child: Text('test'), flex: 3),
            Expanded(child: Text('test'), flex: 6),
            Expanded(child: this._getActionsMenu(), flex: 1)
        ];
    }

    Widget _getActionsMenu() {
    return Container(
        padding: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 0.0),
        child: IconButton(
          icon: Icon(Icons.arrow_forward_ios),
          color: Colors.grey[400],
          onPressed: () {
            showModalBottomSheet<void>(
                context: context,
                builder: (BuildContext context) {
                  return new Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      new ListTile(
                        leading: new Icon(Icons.train),
                        title: new Text(Utility.format(
                            Language.of(context).takePlace, [_place.title])),
                        onTap: () {
                          showUserStatusDialog<DialogActions>(
                              context: context,
                              //It opens a simple dialog
                              child: this._getCurrentUserPlaceStatus());
                        },
                      ),
                    ],
                  );
                });
          },
        ));
    }

    Widget _getCurrentUserPlaceStatus() {
    return new GraphqlProvider(
        client: new ValueNotifier(
          Client(endPoint: 'GraphQLUrl', cache: new InMemoryCache()),
        ),
        child: new Query(
          'The GraphQL Query',
          variables: {},
          builder: ({
            bool loading,
            var data,
            var error,
          }) {
            if (data != null && data['getCurrentUserPlaceStatus'] != null) {
              this._isOtherPlaceActive = UserPlaceStatusType.THERE;
              Navigator.pop(context, DialogActions.cancel);
              return Container();
            } else {
              this._isOtherPlaceActive = UserPlaceStatusType.GOING;
              Navigator.pop(context, DialogActions.cancel);
              return Container();
            }
          },
        ));
    }

    void showUserStatusDialog<T>({BuildContext context, Widget child}) async {
        //here there is a validation but the variable value is the initial one, I mean NONE
        if (this._isOtherPlaceActive == UserPlaceStatusType.GOING) {
            //Cod to do    
            return;
        }

        showDialog<T>(
        context: context,
        builder: (BuildContext context) => child,
        ).then<void>((T value) {
        if (value != null) {
            this._isOtherPlaceActive = UserPlaceStatusType.NONE;
            Navigator.pop(context);
        }
        });
    }
}

我通过一些方法更改了变量值,但是当我需要应用验证时,这是初始值,它没有更改,我无法应用 SetState 方法,因为它破坏了模式并引发了异常。

如有任何反馈,我将不胜感激。

【问题讨论】:

  • 哪些变量更改不起作用?使用setState()时遇到什么错误?
  • 这个变量_isOtherPlaceActive的变化,没有反映出来,它总是有初始值,我猜setState的问题是关于动画的,当简单的对话框开始时它无法重建操作,以及 GraphQL 提供程序发生时
  • 它表明问题出在 AnimationController 并且它还说:另一个异常被抛出:setState() 或 markNeedsBuild() 在构建期间调用。
  • 您发布的代码不包括对 setState 的任何调用...无论如何,您不能在构建过程中调用它,它通常是为了响应用户操作而完成的。 onTap: () =&gt; setState(() =&gt; doSomething()),.
  • 是的,但问题是在 if (data != null && data['getCurrentUserPlaceStatus'] != null) 中应用 else 情况时:this._isOtherPlaceActive = UserPlaceStatusType.GOING; Navigator.pop(context, DialogActions.cancel);返回容器();它会在 showUserStatusDialog 发生时出现该问题,在 showDialog 进行处理时会发生该问题,如果更改变量,则不会发生该问题,该问题不会停止应用程序,但这是控制台中的异常。

标签: dart flutter


【解决方案1】:

方法setState() 不能直接在小部件内部调用。我很好奇您对GrapQLProvider 的使用,因为它返回一个空的Container() 小部件只是为了检查数据的状态。

虽然我不熟悉GraphQL 的用法,但如果您使用的client 继承了StreamFuture,则它可用于在查询完成时进行侦听。

这里有一些 sn-ps 作为演示。让 _testFuture() 作为 Future 回调的示例。

Future _testFuture() async{
  return null;
}

Future 可以在 Widget 中收听。请求完成后,我们有机会致电setState()

_testFuture().then((value) {
  // Check for values here
  setState(() {
    // Update values
  });
});

或者如果请求设置在Stream 中,也可以在Widget 中监听Stream 的变化。

_streamController.add(_testFuture());
  _streamController.stream.listen((event) {
  // Check for values here
  setState(() {
     // Update values
  });
});

这可能不是您正在寻找的确切答案,但我希望这可以指导您找到解决方法的方法。我还发现了一个GraphQL sample,它使用ObservableQuery 作为流,你可以试试。

【讨论】:

    【解决方案2】:

    您的代码非常复杂,应该重构。请注意必须如何调用对话框。

    enum DialogResult {ok, cancel}
    

    caller_widget.dart

    FlatButton(
      child: Text('Open dialog'),
      onPressed: () async {
        // Call dialog and wait for result (async call)
        final dialogResult = await showDialog<DialogResult>(
          context: context,
          builder: (context) => DialogWidget(),
        );
        if (dialogResult == DialogResult.ok) {
          // do something
        }
      },
    ),
    

    dialog_widget.dart

    ...
    FlatButton(
      child: Text('Ok'),
      onPressed: () => Navigator.pop(context, DialogResult.ok), // DialogResult.ok returns
    ),
    FlatButton(
      child: Text('Cancel'),
      OnPressed: () => Navigator.pop(context, DialogResult.cancel), // DialogResult.cancel returns
    ),
    

    所以您可以返回所需的值对话框并将其设置为所需的变量。

    附:尽量避免使用old fashion then 期货进程,使用async/await

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 2013-06-28
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 2016-05-06
      相关资源
      最近更新 更多