Flutter Navigator.pu sh -> вторая страница не обновляет состояние sh с новыми значениями - PullRequest
1 голос
/ 03 мая 2020

В моем приложении есть простой почтовый модуль, который показывает "сердца" на обзоре постов и на странице с подробностями постов. На обеих страницах пользователь может «опубликовать» сообщение, сделав так, чтобы записать идентификатор пользователя в документ пожарного депо и увеличить общий счетчик сообщений.

Проблема заключается в том, что если сообщение прослушивается на странице обзора, а затем пользователь переходит на страницу сведений, новый счетчик и новый статус «нерешенный» не отображаются. Кажется, что состояние не устанавливается заново после перехода на следующую страницу. Переменные кажутся правильными, поскольку я проверял различные операторы печати. После того, как я снова вручную коснусь сердца, отобразятся правильный счетчик и состояние сердца.

Как я могу таким образом заставить setState после команды navigator.pu sh?

Навигация с первой страницы:

GestureDetector(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => new PostPage(postData: widget.postData)));
      }, [...] )

Компонент Hearts - отдельный файл .dart, который включается как на страницах обзора, так и на страницах сведений о публикациях:

class _PostStatsState extends State<PostStats> {

  var _heartsIcon = Icons.favorite;
  dynamic _hearts = -1;
  dynamic _setState = false;

  Future<String> getUserId() async {
      final prefs = await SharedPreferences.getInstance();
      return prefs.getString('userId');
  }

  @override
  Widget build(BuildContext context) {

    final PostModel postData = InheritedPostModel.of(context).postData;

    void setHeartsIcon()async{
      final userId = await getUserId();
      if (postData.heartedBy.contains(userId)) {
        _heartsIcon = Icons.favorite;
      }
      else {
        _heartsIcon = Icons.favorite_border;
      }
    }
      _hearts = widget.hearts;
      setHeartsIcon();
      print("!Set $_hearts $_heartsIcon"); // correct number and icon are printed
[...]

Компонент виджета: // не отображает тот же номер и значок, что и при печати выше

[...]

_showStat(
            _heartsIcon,
            _hearts,
            Colors.red[300],
            _heartOrUnheart
            ),
[...]

Виджет

Widget _showStat(IconData icon, int number,Color color, Function buttonAction) {
    return Column(
      children: <Widget>[
        Padding(
          padding: const EdgeInsets.only(right: 2.0),
          child: IconButton(icon: Icon(icon), color: color,  onPressed: buttonAction,
          enableFeedback: true,),
        ),
        Text(number.toString()),
      ],
    );
  }

Я огляделся и потратил слишком много часов, чтобы исправить это без удачи. Надеюсь, у кого-то есть простое решение для этого.

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Вы можете установить данные в initState, но вы используете InheritedWidgets, поэтому вы должны установить их в didChangeDependencies так:

class _PostStatsState extends State<PostStats> {
  var _heartsIcon = Icons.favorite;
  dynamic _hearts = -1;
  dynamic _setState = false;

  Future<String> getUserId() async {
     final prefs = await SharedPreferences.getInstance();
     return prefs.getString('userId');
  }

  void setHeartsIcon(PostModel postData)async{
    final userId = await getUserId();
    if (postData.heartedBy.contains(userId)) {
      _heartsIcon = Icons.favorite;
    }
    else {
      _heartsIcon = Icons.favorite_border;
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final PostModel postData = InheritedPostModel.of(context).postData;
    _hearts = widget.hearts;
    setHeartsIcon(postData);
    print("!Set $_hearts $_heartsIcon");
  }

  @override
  Widget build(BuildContext context) {

  [....]

Всегда старайтесь поддерживать ваш метод сборки настолько чистым, насколько это возможно.

Альтернативным методом может быть передача данных с предыдущей страницы на эту страницу и установка их в initState, если вы не используете Inhertied widget, за исключением этого.

0 голосов
/ 05 мая 2020
  @override
  Widget build(BuildContext context) {

    return FutureBuilder<void>(
        future: _setHeartsIcon(), // async work
        builder: (context, snapshot) {
           if (snapshot.connectionState == ConnectionState.done) {
            return _showStats();
          }
          else {
            // Otherwise, display a loading indicator.
            return _showStats();
          }
         },
    );
  }

Возможно, это не самый чистый код, но он гарантирует, что _showStats () вызывается снова после загрузки всех данных. Поскольку данные только извлекаются из SharedPreferences асинхронно, это, кажется, занимает считанные миллисекунды и в действительности не отображается в пользовательском интерфейсе.

...