Как мне дождаться завершения выполнения асинхронной функции перед рендерингом виджета во Flutter? - PullRequest
1 голос
/ 06 ноября 2019

В моем файле main.dart я хочу проверить, зарегистрирован ли пользователь, чтобы направить его на соответствующий экран. Я использую SharedPrefence для хранения пользовательских данных из Firebase. Как мне сказать моей функции подождать, пока моя асинхронная функция SharedPreference завершит выполнение, прежде чем она сможет отобразить соответствующий виджет.

Ниже мой код

  Widget _gotoHomeScreen() {
  AuthService.getuserPrefEmail().then((email) {
  print(email);
  AuthService.email = email;
  if (email == null) {
    return LoginScreen();
  } else {
    AuthService.uid = email;
    return HomeMenuScreen();
  }
});

}

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Вам не нужно ждать сборки, вам нужно что-то построить, чтобы показать пользователю, что приложение что-то загружает (или пустой экран), а затем перестроить после завершения функции.

У вас может быть переменная Widget, которая устанавливается по умолчанию при создании виджета, скажем, с помощью CircularProgressIndicator, а затем изменить его с помощью setState, что-то вроде этого:

class YourWidgetState extends State<YourWidget> {
  Widget _body = CircularProgressIndicator();  // Default Body

  @override
  void initState(){
    _gotoHomeScreen();
  }

  @override
  Widget build(BuildContext context){
    return _body;
  }

  Widget _gotoHomeScreen() {
    AuthService.getuserPrefEmail().then((email){
      AuthService.email = email;
      if (email == null) {
        setState(() => _body = LoginScreen());
      } else {
        AuthService.uid = email;
        setState(() => _body = HomeMenuScreen());
      }
    });
  }
}

Другой способ состоит в том, чтобы использовать переменную для информирования вас о ситуации загрузки, например bool finishedLoading, и вызывать setState, чтобы изменить значение, когда это будет сделано, используя переменную email, которую вы установили, чтобы знать, когдапользователь вошел в систему и выполняет условную сборку, например:

bool loading = true;

@override
Widget build(BuildContext context){
  if(loading) return CircularProgressIndicator();

  if(AuthService.email == null)
    return LoginScreen();
  else
    return HomeMenuScreen();
}

Widget _gotoHomeScreen() {
  AuthService.getuserPrefEmail().then((email){
    AuthService.email = email;
    if (email != null) {
     AuthService.uid = email;
    }
    setState((){ loading = false; });
  });
}
0 голосов
/ 06 ноября 2019

Используйте простой FutureBuilder!

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

FutureBuilder<Email>(
future: AuthService.getuserPrefEmail(),
 builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
  switch (snapshot.connectionState) {
    case ConnectionState.active:
    case ConnectionState.waiting:
     return CircularProgressIndicator();
    case ConnectionState.done:
     if (snapshot.hasError) {
       return Text('Error: ${snapshot.error}');
      }
     .... here route to your screen or set it how you want
  }
 },
)
...