及时从Firestore检索数据(在Widget build(BuildContext context)之外)

时间:2020-11-12 04:42:02

标签: firebase flutter dart google-cloud-firestore

如果您想了解某些情况,我问了类似的问题here。在我的Flutter应用中,您可以发送电子邮件

export default React.memo(IndependentComponent);

如上所述。我知道存储电子邮件和密码可能不是最好的方法,但是它可以工作(如果数据及时到位,它将可以工作)。所以我的问题是,我将在应用程序的开头运行此功能,但有时无法按时加载。

UI代码:

  static getEmailCredentials(String email1, String password1) {
    email = email1;
    passw = password1;
  }

  sendMail() async {
    String username = email;//gets email from db 
    String password = passw;//gets password for email from db

    final SmtpServer = gmail(username, password); //fix one day

    final message = Message()
      ..from = Address(username)
      ..recipients.add("xxx@gmail.com")
      ..subject = "From "+name //need name here from db
      ..html = "<h3>" + emailContent.text + "</h3>";

    try {
      final SendReport = await send(message, SmtpServer);
      Fluttertoast.showToast(
        msg: "Message sent! Hang in there!",
        gravity: ToastGravity.CENTER,
      );
    } on MailerException catch (e) {
      e.toString();
      Fluttertoast.showToast(
        msg: "Message failed to send! Try again?",
        gravity: ToastGravity.CENTER,
      );
    }
  }
}
class EmergencyReport extends StatelessWidget {
  EmergencyReport();

  static String email;
  static String passw;
  final TextEditingController emailContent = TextEditingController();

  @override
  Widget build(BuildContext context) {
    getEmailCredentialsF();//function that calls to db
    DateTime now = DateTime.now();
    DateTime weekAgo = now.subtract(new Duration(days: 7));
    DateFormat formadate = DateFormat('dd-MM');
    String formatedDate = formadate.format(now); // current date formatted
    String weekAgoForm =
        formadate.format(weekAgo); // date from week ago formatted
    countDocuments();
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: Colors.blueGrey,
        body: SingleChildScrollView(
          child: Center(
            child: Column(
              children: <Widget>[
                Align(
                  alignment: Alignment.topLeft,
                  child: Container(
                    width: 54,
                    margin: EdgeInsets.only(top: 44),
                    child: FlatButton(
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                      child: Column(
                        children: <Widget>[Icon(Icons.arrow_back_ios)],
                      ),
                    ),
                  ),
                ),
                Text(
                  "Emergency Report",
                  style: new TextStyle(
                    color: Colors.white,
                    fontSize: MediaQuery.of(context).size.width / 10,
                  ),
                ),
                Card(
                    margin: EdgeInsets.only(top: 30),
                    color: Colors.white,
                    child: Padding(
                      padding: EdgeInsets.all(8.0),
                      child: TextField(
                        controller: emailContent,
                        maxLines: 8,
                        decoration: InputDecoration.collapsed(
                            hintText: "Enter what happened here..."),
                      ),
                    )),
                Container(
                  width: 260,
                  height: 70,
                  padding: EdgeInsets.only(top: 20),
                  child: RaisedButton(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20.0),
                    ),
                    child: Text(
                      "Send",
                      style: new TextStyle(
                        color: Colors.white,
                        fontSize: 38.0,
                      ),
                    ),
                    color: Colors.grey[850],
                    onPressed: () {
                      if (emailContent.text != "") {
                        sendMail();
                        Navigator.of(context).pop();
                      } else {
                        Fluttertoast.showToast(
                          msg: "You need to put a message!",
                          gravity: ToastGravity.CENTER,
                        );
                      }
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

是否有一种方法可以让代码在运行其余代码之前等待从数据库收集该信息?我已经尝试过await和async以及未来的构建器(可能是错误地使用了它们,我才刚刚起步)

感谢您提供的所有帮助

用户界面图片,如果有帮助,UI

1 个答案:

答案 0 :(得分:0)

昨天我已经回答了你

FutureBuilder<DocumentSnapshot>(
          future: firestoreInstance.collection("Users").doc(uid).get(),
          builder: (_,snap){
          return snap.hasData ? Text(snap.data.data()["firstName"]):CircularProgressIndicator();
        },)

现在实现类似 假设您有一个对象,可以避免与UI冲突

class MyDB{
 //...
}

您需要在用户集中获取文档


class MyDB{
  MyDB();
  Map<String,dynamic> userData;
  
  Future<void> getUser() async {
    userData = //...set
  }
}

您还想得到其他东西


class MyDB{
  MyDB();
  Map<String,dynamic> userData;
  Map<String,dynamic> someThingElse;

  Future<void> getUser() async {
    userData = //...set
  }
  Future<void> getSomeThingElse() async {
    someThingElse = //...set
  }
}

,您想要在显示任何内容之前等待所有这些数据可用


class MyDB{
  MyDB();
  Map<String,dynamic> userData;
  Map<String,dynamic> someThingElse;

  Future<void> getUser() async {
    userData = //...set
  }
  Future<void> getSomeThingElse() async {
    someThingElse = //...set
  }
  
  Future getEveryThing() async {
    await getUser();
    await getSomeThingElse();
  }
}

现在在UI中使用该getEverything未来


final myDB = MyDB();
build(){
  return FutureBuilder<bool>(
    future: myDB.getEveryThing(),
    builder: (_,snap){
      if(snap.hasData){
        //myDB.userData and myDB.someThingElse will not be null
      }
      //if we are still waiting for the data
      return CircularProgressIndicator();
    },);
}