Flutter:如何修复FutureBuilder中由setState引起的错误

9 浏览
0 Comments

Flutter:如何修复FutureBuilder中由setState引起的错误

我的目标是在点击ExpansionTile时加载一次Future并存储值,以便在Tile关闭然后重新打开时不再加载Future。

我的当前代码存在以下问题:

I/flutter (30528): 在构建期间调用了setState()或markNeedsBuild()。

I/flutter (30528): 无法标记此Dashboard小部件需要构建,因为框架已经在构建小部件的过程中。

I/flutter (30528): 只有在其祖先小部件当前正在构建时,小部件才能在构建阶段标记为需要构建。允许出现此异常的原因是框架

I/flutter (30528): 在构建子级之前构建父级小部件,这意味着脏子级将始终被构建。

I/flutter (30528): 否则,框架可能在此构建阶段不访问此小部件。

I/flutter (30528): 调用setState()或markNeedsBuild()的小部件是:

I/flutter (30528): Dashboard

I/flutter (30528): 在发生问题的调用时,正在构建的小部件是:

I/flutter (30528): FutureBuilder

我知道错误是什么意思,但我不知道如何修复它。这是我的当前代码:

class Dashboard extends StatefulWidget {

final ValueNotifier pageViewScrollNotifier;

final ValueNotifier pageViewIndexNotifier;

final int pageViewIndex;

Dashboard({this.pageViewScrollNotifier, this.pageViewIndexNotifier, this.pageViewIndex}) : super();

@override

_DashboardState createState() => _DashboardState();

}

class _DashboardState extends State with AutomaticKeepAliveClientMixin {

// 与"with AutomaticKeepAliveClientMixin"一起,这可以防止在切换选项卡时重建列表

// 这提高了性能并减少了数据库通信

@override

bool get wantKeepAlive => true;

Boat selectedBoat = Hive.box("selections").get("selectedBoat"); // 选定的船只

bool latestTrimExpanded = false;

// 最新的修剪,只加载一次

Trim latestTrim;

DateTime date;

DateFormat dateFormat = DateFormat("dd.MM.yyyy");

DateFormat timeFormat = DateFormat("HH:mm");

double satisfaction;

IconData icon;

Color color;

Map trimOptions = {}; // 船只的所有修剪选项

@override

Widget build(BuildContext context) {

return Background(

pageViewScrollNotifier: widget.pageViewScrollNotifier,

pageViewIndexNotifier: widget.pageViewIndexNotifier,

pageViewIndex: widget.pageViewIndex,

child: ListView(

shrinkWrap: true,

physics: const NeverScrollableScrollPhysics(),

children: [

selectedBoat != null

? CustomCard(

child: Column(

mainAxisAlignment: MainAxisAlignment.start,

mainAxisSize: MainAxisSize.min,

crossAxisAlignment: CrossAxisAlignment.start,

children: [

Theme(

data: Theme.of(context).copyWith(dividerColor: Colors.transparent), // 使展开瓦片上下的分隔线透明

child: ExpansionTile(

leading: Icon(

FlutterIcons.settings_oct,

size: 30,

color: Color(Hive.box("configs").get("colors")["black"]),

),

title: Text(AppLocalizations.of(context).translate("trims.latestTrim"), style: Theme.of(context).textTheme.headline2),

maintainState: true,

onExpansionChanged: (value) {

setState(() {

latestTrimExpanded = value;

});

},

),

),

latestTrimExpanded && (latestTrim == null)

? FutureBuilder(

future: DatabaseInstance.trim.getLatestTimeOfBoat(selectedBoat.documentid),

builder: (context, futureSnapshot) {

if (futureSnapshot.connectionState != ConnectionState.done) {

return StandardLoading();

} else {

setState(() {

latestTrim = futureSnapshot.data;

date = latestTrim.time["ts"].first;

satisfaction = latestTrim.evaluation["satisfaction"].first;

icon = satisfactionIcon(satisfaction);

color = satisfactionColor(satisfaction);

Hive.box("configs").get("boatClasses")[Hive.box("selections").get("selectedBoat").boatClass]["trimTemplate"].forEach(

(key, value) {

if (!trimOptions.containsKey(key)) {

trimOptions[key] = value;

}

},

);

});

return Container();

}

},

)

: Container(),

latestTrimExpanded && (latestTrim != null)

? Container() // 占位符,将在FutureBuilder中加载的数据显示和访问在这里

: Container(),

],

),

)

: Container(),

],

),

);

}

}

0
0 Comments

在Flutter中,当在FutureBuilder或StreamBuilder中使用setState时会出现错误。这是因为在这些构建器中,不允许使用setState。

虽然如此,有时在这些构建器中确实需要使用setState的效果。在这种情况下,可以尝试使用provider模式来解决问题。在Flutter中,provider模式被推荐使用。

感谢尝试帮助,但我已经通过问题下面的答案解决了这个问题。

0