#flutter #flutter-layout #flutter-dependencies
#flutter #flutter-layout #flutter-зависимости
Вопрос:
Я продолжал сталкиваться с проблемой, из-за которой вы вызываете setState
, когда виджет не смонтирован (особенно после выборки данных). Мой вопрос:
Могу ли я расширить State
класс и переопределить setState
вот так
abstract class MountedState<T extends StatefulWidget> extends State<T> {
@override
void setState(fn) {
if(mounted) super.setState(fn);
}
}
Я сделал это, и это сработало. Я просто хочу знать, не идеально ли это, или я не должен
Future<void> fetchSubjectsAndClasses() async {
try {
Response res = await TeachersAPI.classesAndSubjects();
classes = res.data;
setState(() {});
} catch (e) {
print(e);
}
}
Это моя выборка данных, которая вызывает проблему. Он вызывается на initState
Комментарии:
1. Если вы постоянно вызываете
setState
, когда виджет не смонтирован, вы, вероятно, делаете что-то неправильно.2. Я думаю, как @ChristopherMoore. Обычно этого не должно происходить.
3. Он вызывается не последовательно
setState
. У меня есть виджеты, которые делают сетевые запросы для получения данных. Затем вызовите setState после извлечения данных. Но пользователь, возможно, изменил маршрут до того, как данные были возвращены. В котором затем будет вызван setState, но, конечно, виджет больше не доступен, поэтому он выдает ошибку @ChristopherMoore @NiklasLehnfeld4.Я не говорил, что вы постоянно вызываете
setState
. Я сказал, что вы постоянно звонили,setState
когда виджет не смонтирован. Из того, что я могу сказать, вы, похоже, выполняете какой-то асинхронный вызов безFutureBuilder
, у которого нет проблем, которые вы описываете. Вам нужно поделиться тем, что вы делаете, что генерирует ошибки без вашего специального класса.5. Я извлекаю данные без
FutureBuilder
. Затем обновляю пользовательский интерфейс, как только я закончу выборку
Ответ №1:
Это не идеально. Вы должны использовать FutureBuilder
при работе с асинхронными функциями, которые имеют дело с пользовательским интерфейсом. Это не обязательно, но оно устраняет более раздражающие части обновления пользовательского интерфейса с Future
данными.
Вы должны получить свое будущее в initState
и сохранить его в State
виджете. Затем передайте это вашему FutureBuilder
в build
:
Future myFuture;
@override
void initState() {
super.initState();
myFuture = futureCall();
}
@override
Widget build() {
return FutureBuilder(
future: myFuture,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
//Show widget that has data
}
else if (snapshot.hasError) {
//Show widget that has error
}
else {
//Show widget while loading
}
}
);
}
Комментарии:
1. Хорошо, спасибо! Однако, есть ли какая-либо причина, по которой я не должен использовать метод, описанный в моем вопросе?
2. @NduJay Это предотвращает проблемы, подобные той, с которой вы сталкиваетесь в настоящее время, и это значительно проще практически во всех ситуациях. Это также может быть более эффективным в зависимости от элементов окружения.
3. Да, я это понимаю. Например, решение также предотвращает эти проблемы, и я могу легко использовать его в своем виджете, расширив мой
MountedState
вместоState
. Есть ли какая-либо конкретная причина, по которой я не должен использовать пользовательскийMountedState
класс. Еще раз спасибо4. @NduJay Это значительно проще в использовании и может быть более эффективным. Кроме того, ваша текущая проверка может не сработать, если виджет уничтожается и еще не размонтирован.
5. @NduJay То, что вы делаете, не неправильно , но это шаблонно.