If you would like some context I asked a similar question here . In my flutter app you are able to send emails
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,
);
}
}
}
As seen above. I know it's probably not the best to store the email and password but it works (well it would work if the data came in time). So my problem is I'll run this function at the beginning of the app but sometimes it won't load in on time.
UI Code:
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"]));
});
}
Is there a way to make the code wait for that information to be gathered from the db before running the rest? I've tried await and async and future builders (could have used them wrong I am fairly new to flutter)
Thank you for all the help you give
Pic of UI if it helps UI
yesterday I've answered you this
FutureBuilder<DocumentSnapshot>(
future: firestoreInstance.collection("Users").doc(uid).get(),
builder: (_,snap){
return snap.hasData ? Text(snap.data.data()["firstName"]):CircularProgressIndicator();
},)
now implement the same like Lets say you have a Object which you keep saperate from UI
class MyDB{
//...
}
and you need to get document in users collection
class MyDB{
MyDB();
Map<String,dynamic> userData;
Future<void> getUser() async {
userData = //...set
}
}
and you want to get something else
class MyDB{
MyDB();
Map<String,dynamic> userData;
Map<String,dynamic> someThingElse;
Future<void> getUser() async {
userData = //...set
}
Future<void> getSomeThingElse() async {
someThingElse = //...set
}
}
and you want to wait for all these data to be available before you show anything
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();
}
}
now use that getEverything future in UI
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();
},);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.