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 {