Flutter setState не обновляет дочерний элемент - PullRequest
0 голосов
/ 07 апреля 2020

У меня есть InkWell, который использует onTap для выполнения некоторых действий. Когда кнопка нажата, мне нравится показывать индикатор (в случае, если действие длится долго). Тем не менее, setState в InkWell не приводит к повторной визуализации дочерних элементов. Код выглядит следующим образом:

class PrimaryButtonState extends State<PrimaryButton> {

bool _apiCall;

Widget getWidget() {
  if(_apiCall) {
    return new CircularProgressIndicator();
  } else {
    return Text(
      widget.label,
    );
  }
}

@override
Widget build(BuildContext context) {
  final List<Color> colors = //omitted

  return InkWell(
    child: Container(
      decoration: // omitted
      child: getWidget(), // not updated when _apiCall changes !!!!!
    ),
    onTap: () {
      setState(() {
        _apiCall = true;
      });
      widget.onTab(context);
      setState(() {
        _apiCall = false;
      });
    }
  );
}
}

Как я могу решить, что getWidget возвращает правильный виджет в зависимости от _apiCall?


РЕДАКТИРОВАТЬ:

widget.onTap содержит следующее:

void performLogin(BuildContext context) {
final String userName = _userName.text.trim();
final String password = _password.text.trim();

UserService.get().loginUser(userName, password).then((val) {
  Navigator.push(
      context, MaterialPageRoute(builder: (context) => MainLayout()));
}).catchError((e) {
  // omitted
});

}

передается вместе с виджетом:

class PrimaryButton extends StatefulWidget {

  final bool isPrimary;
  final String label;
  final Function(BuildContext context) onTab;

  PrimaryButton(this.label, this.isPrimary, this.onTab);

  @override
  State<StatefulWidget> createState() => PrimaryButtonState();

}

Моя главная проблема в том, чтобы данный * Метод 1022 * не должен знать, что он «связан» с виджетом пользовательского интерфейса и поэтому не должен setState. Кроме того, так как это общая реализация кнопки, мне нравится, что она взаимозаменяема (поэтому onTap не является жестко заданной)

1 Ответ

1 голос
/ 07 апреля 2020

Похоже, ваша проблема в том, что вы дважды вызываете setState() в своей функции onTap(). Поскольку onTap() не является асинхронной функцией c, она установит _apiCall = true в первом setState, затем сразу же запустит widget.onTab(context), а затем сразу же выполнит второй setState (), чтобы установить _apiCall = false, чтобы вы никогда не видели загрузочный виджет .

Чтобы это исправить, вам нужно сделать функцию onTab асинхронной c функцией и дождаться значения в функции onTap для вашего InkWell:

onTap: () async {
      setState(() {
        _apiCall = true;
      });
      await widget.onTab(context);
      setState(() {
        _apiCall = false;
      });
    }

Это также позволит вы используете результаты своей функции onTab для отображения ошибок или других функций, если это необходимо.

Если вы не уверены, как использовать асин c функции и фьючерсы здесь является хорошим руководством по этому вопросу. это касается именно этого вида использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...