Получение и хранение пользовательских данных после входа / регистрации - PullRequest
0 голосов
/ 06 января 2019

Я хочу загрузить информацию профиля пользователя из firestore после того, как пользователь войдет в систему, и я хочу, чтобы эти данные были доступны всему приложению при входе в данные. Я планирую выполнить последующую часть, используя унаследованные виджеты во флаттере. Я могу правильно загрузить данные из firestore и получить все данные, но домашняя страница не ждет загрузки данных, прежде чем продолжить, поэтому я получаю ошибки. Он вызывает метод, затем игнорирует часть ожидания в методе и продолжает работу, поэтому я получаю ошибки, затем после ошибок я получаю сообщения с данными, которые были загружены.

Я попробовал пару вещей. У меня есть весь код управления пользователями (логин, регистрация, ...) в одном файле, и я написал метод getuserProfie() в этом файле. Метод получает все данные, заполняет пользовательскую модель данными и возвращает эту модель. Смотрите код ниже.

 getUserProfile() async {
    UserModel theUser;
    await FirebaseAuth.instance.currentUser().then((user) {
     Firestore.instance
      .collection('/users')
      .where('uid', isEqualTo: user.uid)
      .snapshots()
      .listen((data) {
    print('getting data');
    theUser = new UserModel(user.uid, data.documents[0]['email'],);

    print('got data');
    print(theUser.email);
    return theUser;
  });
}).catchError((e) {
  print("there was an error");
  print(e);
});
}

Затем я вызываю этот метод на своей домашней странице следующим образом

      @override
      void initState() {
      Usermode user = UserManagement().getUserProfile(); //Calling the method
      super.initState();
      }

Это вызывает метод очень хорошо и получает все данные, но программа не ждет, пока данные будут получены, чтобы продолжить. Я попытался переместить код, который получает данные, в метод initState() и вызвать super.initState(), когда я был уверен, что есть значение, но оно не работает. Я также пытался вызвать getUserProfile() перед вызовом super.initstate(), но это не сработало.

Я попытался добавить асинхронный заголовок initState(), но флаттер не нравится. Я могу получить данные из firebase нормально, но проблема в том, чтобы заставить программу ждать, пока данные не будут получены. Похоже, использование await и async не работает. Любые другие предложения, чтобы убедиться, что данные загружаются, прежде чем продолжить? Я думал об использовании FutureBuilder, но я не уверен, как это будет работать в этом случае.

Ответы [ 3 ]

0 голосов
/ 06 января 2019

initState() не может быть функцией async.

То, что вы можете попробовать, - переместить Usermode user = await UserManagement().getUserProfile(); в новую async функцию.

Usermode user;

@override
void initState() {
super.initState();
_getUser();

}

Void _getUser() async {
user = await UserManagement().getUserProfile();
setState(() {});
}

и в методе сборки вы можете проверить значение пользователя, а затем передать виджеты.

@override
  Widget build(BuildContext context) {
    if (user != null) {
      return ProfilePage();
    } else {
      return CircularProgressIndicator();
    }

Теперь, когда пользовательские данные загружаются, он будет вызывать setState(), и ваша страница профиля будет загружена.

Для этого нужно сделать - Usermode user; переменная состояния.

0 голосов
/ 07 января 2019

После долгих исследований я использовал Flutter StreamBuilder. Это было прекрасно для того, для чего я хотел его использовать. Я вызываю метод UserManagement().getUserProfile() и получаю снимок данных из возвращенного значения. Если данные загружаются, я отображаю CircularProgressIndicator(). Если снимок нулевой, я отображаю сообщение об ошибке. См. Фрагмент кода ниже.

    @override
   Widget build(BuildContext context) {
   return StreamBuilder(
    stream: UserManagement().getClientProfile(curUserID).snapshots(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.active) {
      UserModel _user = new UserModel.from(snapshot.data)
        return Scaffold(
            body: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                 Text(_usermodel.name),
            ],
       });
     }else if (snapshot.connectionState == ConnectionState.waiting) {
        return Container(child: Center(child: CircularProgressIndicator()));
      } else {
        return Container(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Icon(Icons.warning),
              ),
              Text('There was an error please try again')
            ],
          ),
        );
      }
  }

В этом примере я использую StreamBuilder, но вы также можете использовать FutureBuilder. StreamBuilder прослушивает изменения данных и соответственно обновляет пользовательский интерфейс, в то время как FutureBuilder получает данные один раз, пока страница снова не загрузится. Мне пришлось внести изменения в UserModel, а также настроить способ хранения данных, но все получилось. Получил большую часть моего решения от здесь

0 голосов
/ 06 января 2019

Поскольку getUserProfile равно async, вам нужно будет использовать await при вызове:

@override
void initState() async {
  Usermode user = await UserManagement().getUserProfile();
  super.initState();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...