Как было сказано в комментариях, невозможно иметь асинхронные валидаторы, поскольку ожидается, что validator
вернет a String
, а не "Future".
Однако в вашем коде есть ряд неправильных вещей.Прежде всего, validatePhone
возвращается до установки _isValid
, поэтому вы получаете значение null
, потому что оно никогда не было установлено на что-либо.Ваш запрос завершается после возврата validatePhone
и настройка _isValid
в этот момент бесполезна.
Давайте попробуем исправить validatePhone:
Future<bool> validatePhone(number) async {
bool _isValid;
final val = await Requests.get(
"http://apilayer.net/api/validate?value=$number",
json: true);
if (val['valid']) {
// setState(() {
_isValid = true;
// });
} else {
// setState(() {
_isValid = false;
// });
}
return _isValid;
}
, как вы видите, его возвращаемое значение должно было стать Future<bool>
, а не bool
.Нет способа это исправить.Если validator
было разрешено вернуть Future
, то это могло бы сработать.
Вам нужно будет реализовать свою логику валидации нестандартным мучительным способом.
Редактировать: вот вам и нестандартный болезненный способ:)
String lastValidatedNumber;
String lastRejectedNumber;
// this will be called upon user interaction or re-initiation as commented below
String validatePhone(String number) {
if (lastValidatedNumber == number) {
return null;
} else if (lastRejectedNumber == number) {
return "Phone number is invalid";
} else {
initiateAsyncPhoneValidation(number);
return "Validation in progress";
}
}
Future<void> initiateAsyncPhoneValidation(String number) async {
final val = await Requests.get(
"http://apilayer.net/api/validate?value=$number",
json: true);
if (val['valid']) {
lastValidatedNumber = number;
} else {
lastRejectedNumber = number;
}
_formKey.currentState.validate(); // this will re-initiate the validation
}
Вам нужен ключ формы:
final _formKey = GlobalKey<FormState>();
И ваша форма должна автоматически проверяться:
child: Form(
key: _formKey,
autovalidate: true,
child: TextFormField(
validator: validatePhone
)
)
Я не уверен на 100%, будет ли это работать, ноэто стоит попробовать.