我遇到了非常高水平的小部件重建问题。特别是当页面之间发生任何导航时。
应用背景:
我本质上是在构建一个用于创建和显示收藏集的应用程序(在这种情况下为房屋植物)。身份验证,数据库和图像存储都通过Firebase进行。然后,该数据通过流传递到小部件。我所有的自定义小部件当前都是无状态的。
主要页面结构摘要:
我有一个显示该信息的主“图书馆”页面。此页面有一列,其中包含“组”窗口小部件列表。该列的主要窗口小部件结构如下:
等...
显然,组,集合和plantTiles的数量将根据用户提交给数据库的内容而有所不同。
问题:
每次我在应用程序中的页面之间导航时,每个植物Tile都不重建一次,而是重建5次。在示例图像中,这些图块中有49个,导致245次重建。 plantTiles是无状态的,但包装在StreamBuilder中以显示数据。这些小部件包含图像和阴影,这似乎在重建系统上非常费力。
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在每次屏幕构建时触发都可能存在问题。我尝试遵循其他指南来解决此问题,但我一定会错过一些东西,因为我似乎无法阻止它。
任何帮助将不胜感激!我对此并不陌生,所以希望我没有做根本上错误的事情。