Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 在带参数的命名路由中使用FutureBuilder_Flutter - Fatal编程技术网

Flutter 在带参数的命名路由中使用FutureBuilder

Flutter 在带参数的命名路由中使用FutureBuilder,flutter,Flutter,我有一个列表视图,它表示一个对话列表(收件箱)。当用户点击列表项(会话)时,我们将推送到一个以会话id为参数的命名路由。 在新窗口中,我们根据传递的参数(对话id)使用FutureBuilder获取对话消息(http请求) 一切都很好,除了当用户单击back按钮时,会再次调用build方法,并在窗口开始关闭时发出新的http请求 我知道不建议在build方法中创建Future,但在这种情况下,获得传递参数的最佳方法是什么 未来必须更早获得,例如在State.initState、State.did

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

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

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

未来必须更早获得,例如在State.initState、State.didUpdateConfig或State.didChangeDependencies期间。在构造FutureBuilder时,不能在State.build或stateWidget.build方法调用期间创建它。如果future与FutureBuilder同时创建,则每次重建FutureBuilder的父级时,异步任务都将重新启动

以下是我的简化代码:

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"));
            }));
  }
}
类消息扩展StatefulWidget{
@凌驾
_MessagesState createState()=>\u MessagesState();
}
类_MessagesState扩展状态{
@凌驾
小部件构建(构建上下文){
最后一个字符串conversationID=ModalRoute.of(context).settings.arguments;
打印(“Conv:$conversationID”);
最终消息=Api.getMessages(conversationID);
返回脚手架(
appBar:appBar(
标题:文本(“消息”),
),
正文:未来建设者(
未来:信息,
生成器:(BuildContext上下文,异步快照){
交换机(快照.连接状态){
案例连接状态。无:
案例连接状态.active:
案例连接状态。正在等待:
返回中心(子项:CircularProgressIndicator());
案例连接状态。完成:
if(snapshot.hasError)
返回文本('Error:${snapshot.Error}');
}
返回中心(子:文本(“消息”));
}));
}
}
在这里,build方法被调用两次:一次是在窗口打开时,一次是在窗口关闭时,发出两个http请求


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

您应该从_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);
      }
。。。 未来用户

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

child:FutureBuilder(
未来:未来用户,
生成器:(上下文,快照){
if(snapshot.hasData){

Future get\u datos\u user\u应用程序(字符串键,字符串UID)异步{

当我试图调用initState()中的conversationID=ModalRoute.of(context).settings.arguments;时,它抛出一个错误:“通常,对继承的小部件的引用应该出现在小部件构建()中方法。或者,基于继承的小部件的初始化可以放在didChangeDependencies方法中,该方法在initState之后调用,并且在依赖项发生更改时调用。“好的,在我的例子中,我所做的是直接用类所需的信息初始化类,我已经更新了答案
Future navigateToMainMenu(context, uid) async {
  Navigator.push(context,
      MaterialPageRoute(builder: (context) => mainMenu(firebase_uid: uid)));
}
  @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 {