1. Проблема
Я использую динамический try-catch-finally
1 для обработки исключений для Firebase в моем простом пакете аутентификации для моего приложения. В нем, когда я получаю сообщение об ошибке от службы аутентификации Firebase, я обновляю labelText
в (настраиваемом) TextFormField
, чтобы показать пользователю, что произошла ошибка.
Однако notifyListeners()
, очевидно, выполняется одновременно с предложением catch
, из-за чего перестройки не происходят синхронно с обработкой исключений.
В настоящее время я использую ChangeNotifierProvider
практически для всего, но должен ли я перейти на FutureProvider
динамический. Если да, то как лучше всего это сделать?
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 Мой пользовательский TextFormField
виджет
Примерно так есть в приложении:
return Consumer<Auth>(
builder: (context, auth, _) {
return AuthTextFormField(
...,
errorMsgFromServer: auth.errorMsg,
);
}
);
Наконец, кнопка проверки использует formKey.currentState.validate()
в предложении if
для асинхронного запуска await auth.sendPasswordResetWithEmail
.