Asyn c Обработка исключений (Firebase) с пакетом провайдера (флаттер) - PullRequest
0 голосов
/ 19 марта 2020

1. Проблема

Я использую try-catch-finally 1 dynamici c для обработки исключений для Firebase в моем простом пакете аутентификации для моего приложения. В нем, когда я получаю сообщение об ошибке от службы аутентификации Firebase, я обновляю labelText в (настраиваемом) TextFormField, чтобы показать пользователю, что произошла ошибка.

Однако, notifyListeners() явно запускается одновременно с предложением catch, в результате чего перестройки не происходят синхронно с обработкой исключений.

В настоящее время я использую ChangeNotifierProvider для всего, но я должен перейти на FutureProvider Dynami c. Если да, то как лучше это сделать?


1 Я тоже пытался использовать then-catchError-whenComplete.

2. Код

2.1 Полный код (необязательно)

На этом этапе проекта полный код немного длинен, но я думаю, что того, что показано ниже, будет достаточно.

В любом случае, если вы хотите проверить все, доступен весь проект: flutter_firebase_auth_benchmark .

Соответствующие файлы:

  • firebase_auth.dart : provider класс с соответствующими данными.
  • login_screen.dart: email_field подается с provider данными с виджетом Consumer.
  • password_reset_workflow.dart: кнопка, которая вызывает соответствующий метод, вводится в LoginScreen через AnimatedSwitcher.

2.2. Класс провайдера

Мне нужно использовать Future.delayed, чтобы вручную синхронизировать методы notifyListeners() и build() - я знаю, я знаю, это очень плохо ...

class Auth extends ChangeNotifier {
  String _errorMsg;

  String get errorMsg => _errorMsg;

  ...

  Future<void> sendPasswordResetWithEmail({@required String email}) async {
    try {
      await FirebaseAuth.instance.sendPasswordResetEmail(email: email);
    } catch(e) {
      switch (e.code) {
        case 'ERROR_USER_NOT_FOUND':
          _errorMsg = 'user not found';
          break;
        default:
          throw UnknownPasswordResetError(
              'Unknown error for password reset with Firebase.');
      }
    } finally {
      notifyListeners();
      await Future.delayed(Duration(milliseconds: 10));
    }
  }
}

2.3 My Custom TextFormField Виджет

Примерно так находится в приложении:

return Consumer<Auth>(
  builder: (context, auth, _) {
    return AuthTextFormField(
      ...,
      errorMsgFromServer: auth.errorMsg,
    );
  }
);

Наконец, кнопка проверки использует formKey.currentState.validate() в предложении if для асинхронного запуска await auth.sendPasswordResetWithEmail.

1 Ответ

0 голосов
/ 20 марта 2020

notifyListeners (), очевидно, выполняется одновременно с предложением catch

notifyListeners() находится внутри блока finally, finally будет ВСЕГДА выполняться, если вы имели ошибка или нет, поэтому всегда вызывается notifyListeners().

Кроме того, использование Future.delayed для синхронизации событий очень плохо, вам следует создать для него другую архитектуру.

...