Flutter и firebase: как я могу получать данные из функции?

Я использую следующую функцию для получения userData из Firestore:

Future<String>getRegisterUserData({String userID}) async {
Firestore.instance.collection("Users").document(userID).get().then(
  (datasnapshot) {
    if (datasnapshot.exists) {
      return datasnapshot.data['Email'];
    } else {
      return "Loading...";
    }
  },
);
}

Я выполняю эту функцию на моем UserProfilePage следующим образом:

_email = widget.firestore.getRegisterUserData(widget.userID).toString();

Но я всегда получаю распечатку: экземпляр Future, а не сохраненный адрес электронной почты ...

я также пробую это:

Future<String> getRegisterUserData({String userID}) async {
String email;
Firestore.instance.collection("Users").document(userID).get().then(
  (datasnapshot) {
    if (datasnapshot.exists) {
      email = datasnapshot.data['Email'];
    } else {
      email = "Loading...";
    }
  },
);
return email;
}

Заявление о печати всегда одно и то же ...

Так в чем же моя ошибка? Я хочу отобразить значение «Электронная почта» на UserProfilePage в переменной, или моя функция firestore неверна?

Спасибо за нашу помощь

0
0
2 392
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обновлено

Исходя из вашей информации, вам понадобится FutureBuilder, чтобы дождаться ответа для создания вашего виджета:

  return FutureBuilder(
    future: getRegisterUserData(userID: "1234"),
    builder: (context, asyncsnapshot){
      return asyncsnapshot.hasData && asyncsnapshot.data != null ? TextFormField(
        initialValue: asyncsnapshot.data,
      ) : CircularProgressIndicator();
      }
  );

Я добавил ключевое слово await, но проблема все еще не устранена ... Что я также могу сделать, чтобы решить проблему?

Niklas 10.08.2018 18:09

вы уверены, что ваша коллекция и данные существуют? не могли бы вы вернуть только тестовую строку, чтобы убедиться, что

diegoveloper 10.08.2018 18:13

да, пожалуйста, посмотрите так: https://drive.google.com/file/d/1HMrLfXQ_rNWTJeAjpms2YXOao5W‌ RT0Xs / view? usp = shari‌ ng Я не получаю никаких ошибок от firestore, когда добавлял метод catchError ...

Niklas 10.08.2018 18:31

не могли бы вы напечатать что-нибудь: if (datasnapshot.exists) {после этого?

diegoveloper 10.08.2018 18:33

да, это работает ... но в моем приложении я всегда вижу String: Instance of 'Future <String>' Что это значит?

Niklas 10.08.2018 18:38

посмотрите, пожалуйста, на этот снимок экрана: (drive.google.com/file/d/1URMwprJJXoVPh7DhwhmAkoQ7A1x0LV43/…

Niklas 10.08.2018 18:45

нормально работает нормально, распечатайте это: datasnapshot.data ['Email']

diegoveloper 10.08.2018 18:46
widget.firestore.getRegisterUserData(widget.userID) относится к типу Future<String>. вот почему это Экземпляр будущего. Мы должны преобразовать Future <String> в String с помощью await или блока then @diegovelper @Niklas
Dinesh Balasubramanian 10.08.2018 18:59

адрес электронной почты будет напечатан ... так что все работает нормально На моей ProfilePage я добавил функцию на этом этапе: (drive.google.com/file/d/128_c-93XmDTjIc7laAYvHRrrl8WzZALG/… И я всегда получаю String: Instance of 'Future <String>' @diegovelper

Niklas 10.08.2018 19:02

Я добавил еще один ответ ниже

Dinesh Balasubramanian 10.08.2018 19:07

Я обновил свой ответ :), поместите futurebuilder в свой метод buildEmailTextField

diegoveloper 10.08.2018 19:13

@diegoveloper извините, но ваше обновление не работает ... я всегда вижу в своем приложении ProgressIndicator, но не адрес электронной почты ...

Niklas 10.08.2018 19:34

@Niklas, ты ведь возвращаешь данные? обнови свой код

diegoveloper 10.08.2018 19:40

Я не вижу строителя будущего на этом экране

diegoveloper 10.08.2018 19:52

@diegoveloper Что вы имеете в виду под обновлением кода? Я перезагружаю и перезапускаю свое приложение. пожалуйста, посмотрите мой виджет с FutureBuilder: (drive.google.com/file/d/1lpgyO2xpCnxuGfGUWg9ZonyQLL6TysHf/…

Niklas 10.08.2018 19:53

спасибо за вашу помощь и за ваше время :) Вот (Функция Firestore) [drive.google.com/file/d/1pd53ttpOLXO3DZ0kIOOpnMkVB‌ Q-sXWKU /…

Niklas 10.08.2018 19:59

@diegoveloper Ой, извините за ошибку ... большое спасибо, теперь он работает ... у меня последний вопрос: как это работает с автономным хранилищем в Firestore? Например, как я могу сохранить адрес электронной почты, не запрашивая его каждый раз при перезапуске? Спасибо за Ваш ответ...

Niklas 10.08.2018 20:19

По умолчанию Firestore работает в автономном режиме, поэтому проблем у вас не будет. Отметьте ответ как принятый. Если у вас есть другой вопрос, вы можете создать новый выпуск. :)

diegoveloper 10.08.2018 20:21
Ответ принят как подходящий

Добавьте ключевое слово await. Но в другом месте.

tempEmail = await widget.firestore.getRegisterUserData(widget.userID);
setState(() {
  _email = tempEmail;
});
// we don't need toString as getRegisterUserData itself is returning Future<String>

Примечание для использования await: поскольку мы используем await, метод / функция, которые его содержат, должны иметь async в своей сигнатуре.

Или вы можете использовать блок then

widget.firestore.getRegisterUserData(widget.userID).then((email) {
   setState(() {
      _email = email;
   });
});

Объяснение:widget.firestore.getRegisterUserData(widget.userID) относится к типу Future<String>. поэтому он печатается как Экземпляр будущего. Мы должны преобразовать будущее в строку с помощью await или блока then

Использование SharedPreferences:

Future<String> getEmail() async {
  final prefs = await SharedPreferences.getInstance();
  String email = prefs.getString('email');
  if (email != null) {
    return email;
  } else {
    email = await widget.firestore.getRegisterUserData(widget.userID);
    prefs.setString('email', email); //update shared preferences
    return email;
  }
}

// usage (may be in initState)
 widget.getEmail().then((email) {
   setState(() {
     _email = email;
   })
 })

это не работает. Адрес электронной почты не будет отображаться как initialValue в TextFormField. InitialValue не будет отображаться в данный момент ...

Niklas 10.08.2018 19:41

Мы должны использовать setState(() {}) для повторного рендеринга после получения данных. Обновлен ответ соответственно.

Dinesh Balasubramanian 11.08.2018 05:50

спасибо за ваш ответ ... у меня последний вопрос: как я могу сохранить адрес электронной почты, не запрашивая его из Firestore каждый раз, когда приложение перезапускается или страница повторно отображается? Могу ли я использовать для этого метод initState? Как это работает с такими приложениями, как YouTube? Приложение также должно временно кэшировать данные.

Niklas 11.08.2018 22:14

Вы можете использовать Shared_Preference, который лучше всего подходит для быстрого хранения / извлечения небольших данных. Обратитесь к pub.dartlang.org/packages/shared_preferences ...

Dinesh Balasubramanian 12.08.2018 07:34

Если мои ответы полезны, можете ли вы проголосовать / принять?

Dinesh Balasubramanian 12.08.2018 07:34

Не могли бы вы показать мне, как я могу его использовать? (например, для адреса электронной почты) Это было бы очень полезно для меня - спасибо

Niklas 12.08.2018 09:04

Добавлен один пример. Вы можете сослаться на это

Dinesh Balasubramanian 12.08.2018 19:04

Другие вопросы по теме