【问题标题】:Using FutureBuilder in a named route with arguments在带参数的命名路由中使用 FutureBuilder
【发布时间】:2019-12-05 22:35:14
【问题描述】:

我有一个ListView,它代表一个对话列表(收件箱)。当用户点击列表项(对话)时,我们以对话 id 作为参数推送到命名路由。 在新窗口中,我们使用 FutureBuilder 根据传递的参数(对话 id)获取对话消息(http 请求)。

一切都很好,除了当用户单击后退按钮时再次调用 build 方法并在窗口开始关闭时发出新的 http 请求。

我知道不建议在构建方法中创建 Future,但在这种情况下,获取传递的参数的最佳方法是什么。

未来一定是更早获得的,例如在 State.initState、State.didUpdateConfig 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,不能在 State.build 或 StatelessWidget.build 方法调用期间创建它。如果 Future 与 FutureBuilder 是同时创建的,那么每次 FutureBuilder 的 parent 重建时,异步任务都会重新启动。

这是我的简化代码:

class Messages extends StatefulWidget {
  @override
  _MessagesState createState() => _MessagesState();
}

class _MessagesState extends State<Messages> {
  @override
  Widget build(BuildContext context) {
    final String conversationID = ModalRoute.of(context).settings.arguments;
    print("Conv: $conversationID");
    final messages = Api.getMessages(conversationID);
    return Scaffold(
        appBar: AppBar(
          title: Text("Messages"),
        ),
        body: FutureBuilder<dynamic>(
            future: messages,
            builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                case ConnectionState.active:
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                case ConnectionState.done:
                  if (snapshot.hasError)
                    return Text('Error: ${snapshot.error}');
              }
              return Center(child: Text("messages"));
            }));
  }
}

这里build方法被调用了2次:一次是打开窗口,一次是关闭,发出2个http请求。

如果我将消息移到构建方法之外,我将无法访问从 Navigator 传递的 conversationID 参数。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    你应该从你的 _MessageState 覆盖方法 initState;

    @override
      void initState() {
        super.initState();
        final String conversationID = ModalRoute.of(context).settings.arguments;
        final messages = Api.getMessages(conversationID);
      }
    

    另外,你应该在覆盖之上声明你的对象,这样,当你第一次进入屏幕时,它会调用,但下一次它不会。此外,当您将其保存在变量中时,您无需进行进一步调用,它只会加载它保存的内容

    代码示例:

    Future<dynamic> messages;
    @override
          void initState() {
            super.initState();
            final String conversationID = ModalRoute.of(context).settings.arguments;
            final messages = Api.getMessages(conversationID);
          }
    

    其余代码相同。

    希望对你有帮助

    这是我做的一个项目的一个例子:

    [EDIT]类的声明:

    class mainMenu extends StatefulWidget {
      String firebase_uid;
      TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
    
      mainMenu({Key key, @required this.firebase_uid}) : super(key: key);
      Future<UserCompleteObject> user;
    
      @override
      _MyHomePageState createState() => _MyHomePageState(firebase_uid);
    }
    

    [编辑]...导航到班级:

    Future navigateToMainMenu(context, uid) async {
      Navigator.push(context,
          MaterialPageRoute(builder: (context) => mainMenu(firebase_uid: uid)));
    }
    

    ... 未来的future_user;

      @override
      void initState() {
        super.initState();
        //Consigue los datos iniciales de los usuarios
        future_user = get_datos_user_app(key, UUID);
      }
    

    .....

     child: FutureBuilder<UserCompleteObject>(
                future: future_user,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
    

    ...

    Future<UserCompleteObject> get_datos_user_app(String key, String UID) async {
    

    【讨论】:

    • 当我尝试调用 conversationID = ModalRoute.of(context).settings.arguments; 时会引发错误在 initState() 中:“通常对继承小部件的引用应该发生在小部件 build() 方法中。或者,可以将基于继承小部件的初始化放在 didChangeDependencies 方法中,该方法在 initState 之后以及此后依赖关系发生变化时调用。”跨度>
    • 好的,就我而言,我所做的是直接使用课程所需的信息初始化课程,我已经更新了答案
    猜你喜欢
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    相关资源
    最近更新 更多