Как перезагрузить указанные c виджеты во флаттере без его родителя? - PullRequest
1 голос
/ 14 апреля 2020

Я создаю приложение во Флаттере, которое должно быть приложением социальной сети, похожим на faceboook. enter image description here Я реализовал аналогичную кнопку - при нажатии отправляет серверу запрос, а затем в зависимости от кода состояния устанавливает состояние. Моя проблема начинается, когда setState () снова рендерит аватар или создать его заново с нуля (аватар хранится в 64-битной строке). likePress - это будущее, которое отправляет запрос, а затем устанавливает логическое значение isLiked соответственно. это создание кнопки «Мне нравится»:

buildLikeButton(int ownerId, int postId) {
    return RepaintBoundary(
        child: FutureBuilder<bool>(
            future: getLike(ownerId, postId),
            builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
              IconButton likeButton;
              if (snapshot.hasData) {
                isLiked = snapshot.data;
                likeButton = createLikeButton(ownerId, postId);
              } else if (snapshot.hasError) {
                isLiked = false;
                likeButton = createLikeButton(ownerId, postId);
                print('the snapshot has an error ${snapshot.error}');
              } else {
                isLiked = false;
                likeButton = createLikeButton(ownerId, postId);
              }
              return likeButton;
            }));
  }

createLikeButton(int ownerId, int postId) {
    return IconButton(
      icon: returnLikeIcon(isLiked),
      color: Theme.of(context).accentColor,
      onPressed: () async {
        if (this.mounted) {
          setState(() {
            Future lol = likePress(ownerId, postId).then((onValue) {});
          });
        }
      },
    );
  }

и создание аватара:

createAvatar(BuildContext context, avatar_base64, int ownerId) {
    Uint8List bytes = base64Decode(avatar_base64.split(',').last);

    return RepaintBoundary(
        child: CircleAvatar(
      radius: 25.0,
      backgroundImage: MemoryImage(bytes),
      backgroundColor: Colors.transparent,
    ));
  }

Виджет, который отображает их вместе, - это виджет Post, который я создали для этого проекта, и это его функция сборки:

Widget build(BuildContext context) {
return InkWell(
        borderRadius: BorderRadius.circular(0.2),
        child: Container(
          decoration: BoxDecoration(boxShadow: [
            BoxShadow(
              color: Theme.of(context).primaryColor,
              blurRadius: 1.0,
              spreadRadius: 1.0, // has the effect of extending the shadow
              offset: Offset(
                5.0, // horizontal, move right 10
                5.0, // vertical, move down 10
              ),
            ),
          ]),
          child: Card(
              elevation: 10.0,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Flexible(
                      fit: FlexFit.loose,
                      child: postInfo(context, time, ownerId)),
                  Divider(
                    thickness: 1.0,
                    height: 10.0,
                    indent: 10.0,
                    endIndent: 10.0,
                  ),
                  postContent(content),
                  Divider(
                    thickness: 1.0,
                    height: 10.0,
                    indent: 10.0,
                    endIndent: 10.0,
                  ),
                  createButtonBar(ownerId, postId),
                ],
              )),
        ));
  }

postInfo - это просто FutureBuilder, который создает ListTile, который добавляет аватар и имя, а createButtonBar создает кнопку «Мне нравится». и еще 2 кнопки.

Я хотел бы изменить значок, когда пользователь нажимает кнопку «Мне нравится», но только если сервер ответил правильным кодом состояния и без рендеринга и создания всего виджета Post поверх еще раз. Спасибо за беспокойство!

Ответы [ 2 ]

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

Это означает, что аватар находится ниже точки, в которую вы звоните setState (() {}) . В вашем случае метод, вероятно, находится внутри этого конкретного виджета, и виджет перестраивается.

Я предлагаю вам решить проблему, чтобы переместить создание аватара выше. Таким образом, если вам нужно перестроить объект, аватар не будет создан заново, а будет просто помещен в новый виджет. Поместите несколько debugPrint с, чтобы ускорить процесс, и попытайтесь изменить код, чтобы увидеть, пропустили ли вы что-то.

0 голосов
/ 14 апреля 2020

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


, поэтому, если вы хотите исключить виджет из метода setState(), вам нужно переместить его за пределы текущего виджета (создав для него виджет) и просто создать его экземпляр в качестве параметра в конструктор.


Более подробно, я создал класс с именем PostHeader, и там я создал аватар и ListTile, содержащий его, затем я создал его экземпляр внутри Post, поэтому он не создается внутри метода build класса Post.

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