0

My goal is to load a Future once when an ExpansionTile is clicked and store the values, so that the Future isn't loaded again when the Tile gets closed and then reopened.

The problem with my current code is this error:

I/flutter (30528): The following assertion was thrown building FutureBuilder<Trim>(dirty, state:
I/flutter (30528): _FutureBuilderState<Trim>#90a6d):
I/flutter (30528): setState() or markNeedsBuild() called during build.
I/flutter (30528): This Dashboard widget cannot be marked as needing to build because the framework is already in the
I/flutter (30528): process of building widgets.  A widget can be marked as needing to be built during the build phase
I/flutter (30528): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter (30528): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter (30528): Otherwise, the framework might not visit this widget during this build phase.
I/flutter (30528): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (30528):   Dashboard
I/flutter (30528): The widget which was currently being built when the offending call was made was:
I/flutter (30528):   FutureBuilder<Trim>

I know what the error is about, but I have no idea how I can fix it. Here is my current code:

class Dashboard extends StatefulWidget {
  final ValueNotifier<double> pageViewScrollNotifier;
  final ValueNotifier<int> pageViewIndexNotifier;
  final int pageViewIndex;
  Dashboard({this.pageViewScrollNotifier, this.pageViewIndexNotifier, this.pageViewIndex}) : super();

  @override
  _DashboardState createState() => _DashboardState();
}

class _DashboardState extends State<Dashboard> with AutomaticKeepAliveClientMixin<Dashboard> {
  // Togeter with "with AutomaticKeepAliveClientMixin" this prevents the list from rebuilding when switching tabs
  // This increases performance and reduces database communication
  @override
  bool get wantKeepAlive => true;

  Boat selectedBoat = Hive.box("selections").get("selectedBoat"); // Selected boat
  bool latestTrimExpanded = false;

  // Latest trim, only load once
  Trim latestTrim;
  DateTime date;
  DateFormat dateFormat = DateFormat("dd.MM.yyyy");
  DateFormat timeFormat = DateFormat("HH:mm");
  double satisfaction;
  IconData icon;
  Color color;
  Map<String, dynamic> trimOptions = {}; // All trim options the boat has

  @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), // Makes deviders above and below of expansion tile 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() // Placeholder, the data loaded in the FutureBuilder is shown & accessed here
                          : Container(),
                    ],
                  ),
                )
              : Container(),
        ],
      ),
    );
  }
}
PlutoHDDev
  • 540
  • 7
  • 25

1 Answers1

1

You cannot use setstate in future or stream builders just remove the setstate

Hamza Siddiqui
  • 675
  • 5
  • 12