Home > Software design >  setState() or markNeedsBuild() called during build, not clear enough for me
setState() or markNeedsBuild() called during build, not clear enough for me

Time:08-12

I have a provider class in my app:

class TodoProvider extends ChangeNotifier {
  int numUsuarios = 0;
  int numPerfiles = 0;
  int numUbicaciones = 0;
  int numLogs = 0;

  void cambiarNumUsuarios(int s) {

    numUsuarios = s;
    notifyListeners();
  }
  void cambiarNumPerfiles(int s) {

    numPerfiles = s;
    notifyListeners();
  }

  void cambiarNumUbicaciones(int s) {

    numUbicaciones = s;
    notifyListeners();
  }

  void cambiarNumLogs(int s) {

    numLogs = s;
    notifyListeners();
  }

}

Now I need to update, for example, the value for numUsuarios in another class:

 Widget build(BuildContext context) {


    var providerUsuarios = Provider.of<TodoProvider>(context);
    var actualizarNum = Provider.of<TodoProvider>(context, listen: false);

    return SafeArea(
        child: Scaffold(
            backgroundColor: Colors.white,
            appBar: AppBar(
              leading: IconButton(
                icon: Icon(Icons.arrow_back, color: Colors.white),
                onPressed: () => Navigator.of(context).pop(),
              ),
              backgroundColor: Colors.black,
              title: Text(
                "Usuarios (${providerUsuarios.numUsuarios})",//here I want to put numUsuarios value
                style: TextStyle(color: Colors.white),
              ),
            ),
            body: Column(
              children: [
                Row(
                  children: [
                    Flexible(
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: TextField(
                          controller: controlador,
                          onChanged: (value) {
                            textoBuscado = value.toString();
                            setState(() {});
                          },
                          style: TextStyle(),
                          decoration: InputDecoration(
                            prefixIcon: Icon(
                              Icons.search,
                              color: Colors.black,
                            ),
                            hintText: "Buscar usuario",
                            filled: true,
                            fillColor: Color.fromRGBO(235, 235, 245, 0.6),
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(15),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                Expanded(
                  child: StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
                    // inside the <> you enter the type of your stream
                    stream: FirebaseFirestore.instance
                        .collection("usuarios")
                        .snapshots(),
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        return ListView.builder(
                          itemCount: snapshot.data!.docs.length,
                          itemBuilder: (context, index) {
                            //snapshot.data!.docs[index].get('usuarioEmail'),
                           numeroUsuarios = snapshot.data!.docs.length;

                           actualizarNum.cambiarNumUsuarios(numeroUsuarios);//here I want to update numUsuarios value

But I am getting following warning message:

======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for TodoProvider:
setState() or markNeedsBuild() called during build.

This _InheritedProviderScope<TodoProvider?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<TodoProvider?>
  value: Instance of 'TodoProvider'
  listening to value
The widget which was currently being built when the offending call was made was: MediaQuery
  MediaQueryData(size: Size(390.0, 844.0), devicePixelRatio: 3.0, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding: EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, alwaysUse24HourFormat: true, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors: false, boldText: false, navigationMode: traditional, gestureSettings: DeviceGestureSettings(touchSlop: null), displayFeatures: [])
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4476:11)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4491:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:577:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:324:24)
#4      TodoProvider.cambiarNumUsuarios (package:movmap_ns_admin/provider/todos_provider.dart:12:5)
#5      _UsuariosState.build.<anonymous closure>.<anonymous closure> (package:movmap_ns_admin/pantallas/usuarios.dart:147:42)
#6      SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:471:22)
#7      SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:1236:28)
#8      SliverMultiBoxAdaptorElement.performRebuild.processElement (package:flutter/src/widgets/sliver.dart:1169:67)
#9      Iterable.forEach (dart:core/iterable.dart:325:35)
#10     SliverMultiBoxAdaptorElement.performRebuild (package:flutter/src/widgets/sliver.dart:1213:24)
#11     SliverMultiBoxAdaptorElement.update (package:flutter/src/widgets/sliver.dart:1146:7)
#12     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#13     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#14     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#15     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#16     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#17     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#18     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#19     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:5825:32)
#20     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6375:17)
#21     _ViewportElement.update (package:flutter/src/widgets/viewport.dart:237:11)
#22     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#23     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#24     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#25     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#26     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#27     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#28     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#29     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#30     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#31     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#32     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#33     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#34     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#35     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#36     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#37     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#38     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#39     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#40     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#41     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#42     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:6222:14)
#43     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#44     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#45     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#46     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#47     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#48     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#49     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#50     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#51     StatefulElement.update (package:flutter/src/widgets/framework.dart:5009:5)
#52     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#53     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#54     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#55     ProxyElement.update (package:flutter/src/widgets/framework.dart:5154:5)
#56     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#57     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#58     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#59     StatelessElement.update (package:flutter/src/widgets/framework.dart:4883:5)
#60     Element.updateChild (package:flutter/src/widgets/framework.dart:3530:15)
#61     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4832:16)
#62     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4977:11)
#63     Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#64     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#65     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:891:21)
#66     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#67     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#68     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#69     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
#73     _invoke (dart:ui/hooks.dart:151:10)
#74     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#75     _drawFrame (dart:ui/hooks.dart:115:31)

Code line #147 is actualizarNum.cambiarNumUsuarios(numeroUsuarios);

CodePudding user response:

You can use addPostFrameCallback.

builder: (context, snapshot) {
  if (snapshot.hasData) {
    WidgetsBinding.instance.addPostFrameCallback((t) {
      Provider.of<TodoProvider>(context, listen: false)
          .cambiarNumUsuarios(23);
    });

Also try creating state variable for stream, else it will recall the api on every setState

  • Related