【问题标题】:Receiving error "setState() or markNeedsBuild() called during build"收到错误“在构建期间调用 setState() 或 markNeedsBuild()”
【发布时间】:2021-04-12 09:52:09
【问题描述】:

我在此 dart 文件中收到此错误“setState() 或 markNeedsBuild() 在构建期间调用”。在这里,我调用 Futurebuilder 来获取用户()身份验证信息,基本上我正在检查用户是否已登录,然后我将根据相应的屏幕移动到相应的屏幕。

我正在粘贴代码以供参考。谢谢。

import 'package:flutter/material.dart';
import 'package:mukti/ui_pages/login_signup/login_screen.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:mukti/ui_pages/main_screen/main_screen.dart';
import 'package:provider/provider.dart';

import 'authService.dart';

class CheckAuthentication extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FutureBuilder(
        future: Provider.of<AuthService>(context, listen: false).getUser(),
        builder: (context, AsyncSnapshot<auth.User> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.error != null) {
              print("error");
              return Text(snapshot.error.toString());
            }
            return snapshot.hasData ? MainScreen(firebaseUser: snapshot.data) : LoginScreen();
          } else {
            return LoadingCircle();
          }
        }
      )
    );
  }
}

class LoadingCircle extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: CircularProgressIndicator(
          backgroundColor: Theme.of(context).colorScheme.primaryVariant,
        ),
        alignment: Alignment(0.0, 0.0),
      ),
    );
  }
}

参考异常信息

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

This _InheritedProviderScope<AuthService> 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<AuthService>
  value: Instance of 'AuthService'
  listening to value
The widget which was currently being built when the offending call was made was: CheckAuthentication
  dirty
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4292:11)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4307:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:496:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:226:25)
#4      AuthService.getUser (package:mukti/authentication/authService.dart:18:7)
...
The AuthService sending notification was: Instance of 'AuthService'
════════════════════════════════════════════════════════════════════════════════════════════════════

【问题讨论】:

  • 您发布的代码看起来不是错误的来源,它可能在其他小部件MainScreenLoginScreen 上。请发布日志中的错误。
  • 我也这么认为。顺便说一句,您不能直接在构建函数中使用 setState 函数,因为这会导致循环。 StatelessWidgets 中也没有 setStae 函数。
  • 我已经添加了异常,所以你可以检查一下。
  • 尝试获取AuthService并将其存储在构建方法开头的局部变量中,而不是在未来属性中调用它

标签: flutter flutter-layout flutter-futurebuilder


【解决方案1】:

您的问题是在您的 getUser() 函数中调用 notifyListeners()。删除该行,错误就会消失。这会尝试构建小部件树,而 FutureBuilder 正在构建中

【讨论】:

  • 这是真正的正确答案,任何人都想知道
【解决方案2】:

请尝试以下代码:

import 'package:flutter/material.dart';
import 'package:mukti/ui_pages/login_signup/login_screen.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:mukti/ui_pages/main_screen/main_screen.dart';
import 'package:provider/provider.dart';

import 'authService.dart';

class CheckAuthentication extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    final authService = Provider.of<AuthService>(context, listen: false);

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: FutureBuilder(
        future: authService.getUser(),
        builder: (context, AsyncSnapshot<auth.User> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.error != null) {
              print("error");
              return Text(snapshot.error.toString());
            }
            return snapshot.hasData ? MainScreen(firebaseUser: snapshot.data) : LoginScreen();
          } else {
            return LoadingCircle();
          }
        }
      )
    );
  }
}

class LoadingCircle extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        child: CircularProgressIndicator(
          backgroundColor: Theme.of(context).colorScheme.primaryVariant,
        ),
        alignment: Alignment(0.0, 0.0),
      ),
    );
  }
}

【讨论】:

  • 它没有工作仍然收到异常:(
  • 您是否正确接收AuthService?不是null
  • 是的,我打印了运行良好的数据
【解决方案3】:

getUser() 供参考

final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;

  Future<auth.User> getUser() async {
    try {
      final user = _auth.currentUser;
      if (user != null) {
        print('User signed in: ${user.email}');
      } else {
        print('No user signed in');
      }
      notifyListeners();
      return user;
    } catch (e) {
      print(e);
      return null;
    }
  }

【讨论】:

  • 你的问题是 notifyListeners();删除该行,错误就会消失。这会尝试构建小部件树,而 FutureBuilder 正在构建中
  • 谢谢伙计,它成功了,现在错误消失了:):)
  • 欢迎您!您介意接受我创建的答案吗? :)
猜你喜欢
  • 1970-01-01
  • 2020-03-26
  • 2021-11-14
  • 2021-04-21
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
相关资源
最近更新 更多