【问题标题】:Retrieving Data From Firestore in time (outside of Widget build(BuildContext context) )及时从 Firestore 中检索数据(在 Widget build(BuildContext context) 之外)
【发布时间】:2021-02-24 02:40:58
【问题描述】:

如果你想要一些上下文,我问了一个类似的问题here。在我的 Flutter 应用中,您可以发送电子邮件

  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,
                        );
                      }
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
void getEmailCredentialsF() {
  print("Attemping to get email!");
  final firestoreInstance = FirebaseFirestore.instance;
  FirebaseAuth auth = FirebaseAuth.instance;
  String uid = auth.currentUser.uid.toString();
  firestoreInstance.collection("SendMailCredentials").doc("w1HsHFRgq7Oc3X9xUEnH").get().then((value) {
    EmergencyReport.getEmailCredentials((value.data()["email"]),(value.data()["password"]));
  });
}

有没有办法让代码在运行其余部分之前等待从数据库中收集到该信息?我已经尝试过 await 和 async 以及未来的构建器(可能用错了我对颤动还很陌生)

感谢您提供的所有帮助

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

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    昨天我已经回答了你这个问题

    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();
        },);
    }
    

    【讨论】:

    • 感谢您一直以来的帮助。对此,我真的非常感激。当我尝试添加您的代码时,我收到此错误“类型 'Future' 不是 'Future' 的子类型。你知道什么可能会导致这种情况。这里是我的代码的粘贴箱0bin.net/paste/…
    • 更新:所以我可以使用此代码pastebin.com/R9dzcaTH 这样做有什么问题吗?
    • 您在 getUser 处将地图作为字符串处理
    猜你喜欢
    • 2019-06-26
    • 1970-01-01
    • 2021-02-22
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多