如何等待异步函数结束?

时间:2021-07-05 13:04:48

标签: flutter dart asynchronous http-post

我有一个小部件类,它从后端加载用户的消息并将其显示在屏幕上。我在小部件类的构建函数中调用我的异步函数 getConversations 来获取用户的消息。但我不知道如何等待该功能结束。它在我的构建函数返回空列表后结束。这是我的代码:

获取对话:

Future<List<Conversation>> getConversations(BuildContext context) async {
  Map<String,dynamic> conversations;
  try{
    var getMessagesUrl=Uri.http(BackendBaseURL,'/user/messages/');
    print('before post');
    var response = await http.post(getMessagesUrl,body:convert.jsonEncode({'id':_userID}));
    print('after post');
    if(response.statusCode==200){
      conversations=convert.jsonDecode(response.body) as Map<String,dynamic>;
      print(conversations);
      return conversations.entries.map(
        (conversation) => Conversation(
          conversation.key, 
          conversation.value.map(
            (message) => Message(message['message'],message['sent_by_user'],message['send_date'])
          ).toList().cast<Message>()
        )
      ).toList();
    }
    else
      showErrorDialog(context, 'Sunucuya bağlanılamadı.');
  }
  on Exception catch(e){
    print(e);
    showErrorDialog(context, 'Sunucuya bağlanılamadı.');
  }
  return [];
}

构建函数:

@override
Widget build(BuildContext context){
  List<Conversation> conversations=[];

  getConversations(context).then((value) => conversations=value);
  print('then: '+conversations.toString());

  //Need to wait getConversations function here before continuing

  return Scaffold(
    appBar: AppBar(
      title: Text(this._username),
    ),
    body:Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
          
      ]..addAll(conversations),
    ),
  );
}

我的输出是这样的:

I/flutter ( 3034): before post
I/flutter ( 3034): then:[]
I/flutter ( 3034): after post
I/flutter ( 3034): {belkanahmet: [{message: ii sn, sent_by_user: true, send_date: 2021-07-02T15:32:54+03:00}, {message: nbr, sent_by_user: false, send_date: 2021-06-26T21:44:58+03:00}]}

2 个答案:

答案 0 :(得分:0)

您可以使用 Stream Builder Widget。这允许您使用 Connection.state 函数来知道您的流处于哪种状态。然后您只能在连接状态完成等待时运行您的方法

答案 1 :(得分:0)

FutureBuilder 类是我一直在寻找的(感谢@quoci)

使用 FutureBuilder,我能够为不同的数据值返回不同的小部件。在我的情况下,在我从我的 API 得到响应后,我能够从我的构建函数返回一个不同的主体。这是工作代码:

获取对话:

  @override
  Widget build(BuildContext context){
    List<Conversation> conversations=[];

    getConversations(context).then((value) => conversations=value);

    return Scaffold(
      appBar: AppBar(
        title: Text(this._username),
      ),
      body:FutureBuilder(
        future: getConversations(context),
        initialData: [],
        builder: (builder,snapshot){
          if(snapshot.connectionState==ConnectionState.waiting) //While waiting for response return this
            return Center(
              child:CircularProgressIndicator()
            );
          return Column( //After getting response return this
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              
            ]..addAll(conversations),
          );
        },
      ),
    );
  }