简体   繁体   中英

“setState() or MarkNeedsBuild() called during” error in flutter app

I am a beginner in flutter. When I call Settings widget the following error occurs. I tried everyhing that has been posted from the same issue, but nothing changed. When I remove the StreamBuilder it works fine. However, without the StreamBuilder I cannot get the data from cloud firestore and display it in the settings widget.

Here is Home screen where I call the Settings widget .

body: FlatButton.icon(
            onPressed: () {
              Navigator.of(context)
                  .push(MaterialPageRoute(builder: (context) => Settings()));
            },
            icon: Icon(Icons.settings),
            label: Text('User Profile')),
      );

Here is Settings widget

import 'dart:math';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_firebase_test/screens/services/auth.dart';
import 'package:flutter_firebase_test/shared/loading.dart';

class Settings extends StatefulWidget {
  @override
  _Settings createState() => _Settings();
}

class _Settings extends State<Settings> {
  AuthService _auth = new AuthService();
  @override
  Widget build(BuildContext context) {
    Color randomColor() {
      int index = 0;
      List colors = [
        Colors.red,
        Colors.blue,
        Colors.green,
        Colors.yellow,
        Colors.amber,
        Colors.deepPurple
      ];
      Random rnd = new Random();
      setState(() => index = rnd.nextInt(6));
      return colors[index];
    }

    return StreamBuilder<QuerySnapshot>(
        stream: Firestore.instance.collection('users').snapshots(),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Loading();
          } else {
            return Scaffold(
              body: Container(
                padding: EdgeInsets.fromLTRB(30, 80, 30, 0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Center(
                      child: Column(
                        children: [
                          CircleAvatar(
                            backgroundColor: randomColor(),
                            //backgroundImage: AssetImage('assets/avatars/male1.jpg'),
                            radius: 60,
                            child: Text(
                              // TODO: The name will be set later!
                              "Ali"[0].toUpperCase(),
                              style: TextStyle(
                                color: Colors.black,
                                fontWeight: FontWeight.bold,
                                fontSize: 40,
                              ),
                            ),
                          ),
                          SizedBox(
                            height: 20,
                          ),
                          Text("dasdas"),
                        ],
                      ),
                    ),
                    SizedBox(
                      height: 30,
                    ),
                    Divider(
                      color: Colors.black,
                    ),
                    SizedBox(
                      height: 40,
                    ),
                    Wrap(children: [
                      Text(
                        "Name:",
                        style: TextStyle(
                          fontSize: 20,
                        ),
                      ),
                      SizedBox(
                        width: 20,
                      ),
                    ]),
                    SizedBox(
                      height: 40,
                    ),
                    Wrap(children: [
                      Text(
                        "Username:",
                        style: TextStyle(
                          fontSize: 20,
                        ),
                      ),
                      SizedBox(
                        width: 20,
                      ),
                      Text(
                        "User fullname will display here",
                        style: TextStyle(
                          fontSize: 20,
                        ),
                      ),
                    ]),
                  ],
                ),
              ),
            );
          }
        });
  }
}

flutter doctor -v result

] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.19042.685], locale en-US)
    • Flutter version 1.22.5 at C:\src\flutter
    • Framework revision 7891006299 (3 weeks ago), 2020-12-10 11:54:40 -0800
    • Engine revision ae90085a84
    • Dart version 2.10.4       

 
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at C:\Users\demir\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

Debug console:

The following assertion was thrown building StreamBuilder<QuerySnapshot>(dirty, state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#778da):
setState() or markNeedsBuild() called during build.
This Settings 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.

    state: _StreamBuilderBaseState<QuerySnapshot, AsyncSnapshot<QuerySnapshot>>#778da
The relevant error-causing widget was
StreamBuilder<QuerySnapshot>
package:flutter_firebase_test/…/home/settings.dart:31
When the exception was thrown, this was the stack
#0      Element.markNeedsBuild.<anonymous closure>
package:flutter/…/widgets/framework.dart:4292
#1      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4307
#2      State.setState
package:flutter/…/widgets/framework.dart:1264
#3      _Settings.build.randomColor
package:flutter_firebase_test/…/home/settings.dart:27
#4      _Settings.build.<anonymous closure>
package:flutter_firebase_test/…/home/settings.dart:47
...


Put your randomColor method outside the build method. Also you don't need to call setState on your index variable since it's local in that method

Color randomColor() {
  int index = 0;
  List colors = [
    Colors.red,
    Colors.blue,
    Colors.green,
    Colors.yellow,
    Colors.amber,
    Colors.deepPurple
  ];
  Random rnd = new Random();
  index = rnd.nextInt(6);
  return colors[index];
}

// ...

@override
Widget build(BuildContext context) {

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM