不必要的无状态小部件重建(Flutter / Dart)-可能与StreamBuilder相关吗?

时间:2019-11-15 20:39:47

标签: android-studio flutter dart stream rebuild

我遇到了非常高水平的小部件重建问题。特别是当页面之间发生任何导航时。

应用背景:

我本质上是在构建一个用于创建和显示收藏集的应用程序(在这种情况下为房屋植物)。身份验证,数据库和图像存储都通过Firebase进行。然后,该数据通过流传递到小部件。我所有的自定义小部件当前都是无状态的。

主要页面结构摘要:

我有一个显示该信息的主“图书馆”页面。此页面有一列,其中包含“组”窗口小部件列表。该列的主要窗口小部件结构如下:

    • 收藏
      • PlantTile
      • PlantTile
    • 收藏
      • PlantTile
      • PlantTile
      • PlantTile
    • 收藏
      • PlantTile
    • 收藏
      • PlantTile
      • PlantTile

等...

显然,组,集合和plantTiles的数量将根据用户提交给数据库的内容而有所不同。

问题:

每次我在应用程序中的页面之间导航时,每个植物Tile都不重建一次,而是重建5次。在示例图像中,这些图块中有49个,导致245次重建。 plantTiles是无状态的,但包装在StreamBuilder中以显示数据。这些小部件包含图像和阴影,这似乎在重建系统上非常费力。

Widget Rebuild Stats

GridView.builder wraps each plantTile with a StreamBuilder

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:plant_collector/formats/constants.dart';
import 'package:plant_collector/screens/plant.dart';
import 'package:plant_collector/widgets/dialogs/select/dialog_select.dart';
import 'package:provider/provider.dart';
import 'package:plant_collector/models/ui_builders/builders_general.dart';
import 'package:plant_collector/formats/colors.dart';

class TilePlant extends StatelessWidget {
  final Map plantMap;
  final String collectionID;
  final List<dynamic> possibleParents;
  TilePlant({
    @required this.plantMap,
    @required this.collectionID,
    @required this.possibleParents,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onLongPress: () {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return DialogSelect(
              title: 'Move to Another Collection',
              text:
                  'Please select the collection where you would like to move this plant.',
              plantID: plantMap[kPlantID],
              listBuildColumn: Provider.of<UIBuilders>(context)
                  .createDialogCollectionButtons(
                selectedItemID: plantMap[kPlantID],
                currentParentID: collectionID,
                possibleParents: possibleParents,
              ),
            );
          },
        );
      },
      child: Container(
        decoration: BoxDecoration(
          image: plantMap[kPlantThumbnail] != null
              ? DecorationImage(
                  image: CachedNetworkImageProvider(plantMap[kPlantThumbnail]))
              : DecorationImage(
                  image: AssetImage(
                    'assets/images/default.png',
                  ),
                ),
          boxShadow: kShadowBox,
          shape: BoxShape.rectangle,
        ),
        child: FlatButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => PlantScreen(
                  plantID: plantMap[kPlantID],
                  forwardingCollectionID: collectionID,
                ),
              ),
            );
          },
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              plantMap[kPlantName] != null
                  ? Padding(
                      padding: EdgeInsets.all(1.0),
                      child: Container(
                        color: Color(0x44000000),
                        margin: EdgeInsets.all(2.0),
                        padding: EdgeInsets.all(3.0),
                        constraints: BoxConstraints(
                          maxHeight: 50.0,
                        ),
                        child: Text(
                          plantMap[kPlantName],
                          textAlign: TextAlign.center,
                          overflow: TextOverflow.fade,
                          style: TextStyle(
                            fontSize: 10.0,
                            color: Colors.white,
                          ),
                        ),
                      ),
                    )
                  : Container(),
            ],
          ),
        ),
      ),
    );
  }
}

我想要的:

这些小部件没有理由更新。包装到流中的要点是,在最初创建后,仅当传递流事件(用户修改工厂数据)时,才应更新plantTile。因此,理想情况下,导航时对PlantTile的小部件重建将为零(不是5 x 49 = 245),并且如果更改了植物的数据,则将进行1次重建。

我已阅读到StreamBuilders在每次屏幕构建时触发都可能存在问题。我尝试遵循其他指南来解决此问题,但我一定会错过一些东西,因为我似乎无法阻止它。

任何帮助将不胜感激!我对此并不陌生,所以希望我没有做根本上错误的事情。

0 个答案:

没有答案