【问题标题】:How to reload specific widgets in flutter without its parent?如何在没有父级的情况下重新加载特定的小部件?
【发布时间】:2020-04-14 15:16:09
【问题描述】:

我正在用 Flutter 构建一个应用程序,它应该是一个类似于 Facebook 的社交网络应用程序。 我已经实现了一个类似的按钮 - 按下时向服务器发送请求,然后根据状态代码设置状态。我的问题开始于 setState() 再次呈现头像图片,或从头开始重新创建它(头像存储在 64base 字符串中)。 likePress 是发送请求然后相应地设置布尔值isLiked 的未来。 这是like按钮的创建:

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 小部件。谢谢您的麻烦!

【问题讨论】:

  • 只设置被更新的特定对象的状态。
  • 那为什么头像图片又自己渲染了呢?
  • 我建议使用适当的实现,无论是 bloc 还是提供程序。这样你就可以正确处理状态
  • 我不熟悉您的建议,将尝试阅读它们,但现在我仍然希望它能够正常工作而无需再次编写所有内容。

标签: flutter dart flutter-layout


【解决方案1】:

这意味着头像位于您调用 setState(() {}) 的位置下方。在您的情况下,该方法可能位于该特定小部件内,并且正在重建该小部件。

我建议您解决问题,将头像的创建移到上面。这样,如果您需要重建对象,化身将不会被重新创建,而是简单地放置在新的小部件中。放置一些 debugPrint 以加快进程并尝试重构代码以查看是否遗漏了什么。

【讨论】:

  • 显然在调用 setState() 时会运行整个构建方法。有什么方法可以排除再次构建小部件吗?
  • 不,没有。正如文档所述,在某些情况下直接从框架调用 build 方法,其中包括 setState 方法。您最终可以将应用程序逻辑的一部分移至 initState 方法,该方法在小部件的整个生命周期中仅被调用一次,当它被插入到小部件树中时。
【解决方案2】:

在仔细查看了我的代码之后,我决定为帖子的每个部分创建一个不同的 Widget,这样我就可以初始化所有不会在 build 方法之外再次构建的东西。


所以如果你想从setState() 方法中排除一个小部件,你需要将它移到当前小部件之外(通过为它创建一个小部件),并在构造函数。


更详细地说,我创建了一个名为 PostHeader 的类,并在那里创建了头像和包含它的 ListTile,然后我在 Post 类中创建了它的一个实例,因此它不在Post 类的build 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-18
    • 2014-09-17
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2011-11-09
    • 2022-06-10
    • 2017-09-24
    相关资源
    最近更新 更多