GetX unhandled Exception: setState() or markNeedsBuild() called during build – When going to a screen

huangapple go评论49阅读模式
英文:

GetX unhandled Exception: setState() or markNeedsBuild() called during build - When going to a screen

问题

我正在使用GetX。

当我从EventScreen转到HomeScreen -> 一切正常...然后再从EventScreen返回到HomeScreen(使用左侧的抽屉菜单)...第二次返回HomeScreen时出现以下错误:

[GETX] 实例“EventsScreenController”已被初始化
[GETX] 前往路由/HomeScreen
[GETX] 实例“HomeScreenController”已创建
[GETX] 实例“HomeScreenController”已被初始化
[GETX] 前往路由/HomeScreen
[GETX] 前往路由/EventsScreen
[GETX] 前往路由/HomeScreen
[VERBOSE-2:dart_vm_initializer.cc(41)] 未处理的异常:在构建期间调用了setState()或markNeedsBuild()。
此Obx小部件不能被标记为需要构建,因为框架已经在构建小部件的过程中。只有在构建阶段中,如果其祖先之一当前正在构建,才能将小部件标记为需要构建。允许出现此异常,因为框架在构建父小部件之前构建子小部件,这意味着脏的后代将始终被构建。否则,在此构建阶段,框架可能不会访问此小部件。
调用setState()或markNeedsBuild()的小部件是:
  Obx
在发生问题的调用时正在构建的小部件是:
  Builder

为什么第二次返回HomeScreen时会出现这个错误?

HomeScreen中的一些代码:

child: Obx(
  () {
    return controller.isLoading.value
        ? const Center(child: CircularProgressIndicator())
        : controller.isError.value
            ? ErrorCard(
                controller: controller,
                retryFunction: () => controller.getEvents(),
              )
            : controller.events.isEmpty
                ? const Text("There are no events available for the defined filter") //TODO: Show ErrorCard and set retryFuntion: openFilter of events (popup)
                : ListView.builder(
                    // 其余部分...
                  );
  }
)
英文:

I am using GetX.

When I go from EventScreen to HomeScreen -> Everything works...then going back to EventScreen and back to HomeScreen(using Drawer menu from left)...the second time I go back to the HomeScreen this error occurs:

[GETX] Instance "EventsScreenController" has been initialized
[GETX] GOING TO ROUTE /HomeScreen
[GETX] Instance "HomeScreenController" has been created
[GETX] Instance "HomeScreenController" has been initialized
[GETX] GOING TO ROUTE /EventsScreen
[GETX] GOING TO ROUTE /HomeScreen
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: setState() or markNeedsBuild() called during build.
This Obx 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:
  Obx
The widget which was currently being built when the offending call was made was:
  Builder
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4634:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4646:6)
#2      State.setState (package:flutter/src/widgets/framework.dart:1153:15)
#3      _ObxStat<…>

Why this is occurs the second time I go to HomeScreen?

Some code in HomeScreen:

              child: Obx(
                () {
                  return controller.isLoading.value
                      ? const Center(child: CircularProgressIndicator())
                      : controller.isError.value
                          ? ErrorCard(
                              controller: controller,
                              retryFunction: () => controller.getEvents(),
                            )
                          : controller.events.isEmpty
                              ? const Text(
                                  "There are no events available for the defined filter") //TODO: Show ErrorCard and set retryFuntion: openFilter of events (popup)
                              : ListView.builder(
.......)})

答案1

得分: 5

如果您正在使用有状态小部件,并且要在initState方法中更新您的值,请使用以下代码:

initState(){
 super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
  // 在构建后执行
  });
}

注意:您正在在构建小部件之前更新该值。

英文:

If you are using a stateful widget, You are updating your value on the initstate method then please use this.

initState(){
 super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
  // executes after build
  });
}

Notes:- You are updating the value before build widget.

答案2

得分: 2

如日志所述,setState() 或 markNeedsBuild() 在构建期间被调用,这是因为您正在使用 StatefulWidget,或者可能在 initState() 中初始化了某些内容<br>

解决方法是将其改为 StatelessWidget,如果您想在状态创建时初始化某些内容,请使用 GetxController 的 onInit() 方法。

happy coding GetX unhandled Exception: setState() or markNeedsBuild() called during build – When going to a screen

英文:

As the log says setState() or markNeedsBuild() called during build this is because you are using StatefulWidget or may be initialize something in initState()<br>

The solution is to make it StatelessWidget and if you want to initialize something when state is created use onInit() methood of GetxController.

happy coding GetX unhandled Exception: setState() or markNeedsBuild() called during build – When going to a screen

答案3

得分: 0

> 尝试这个

        child: Obx(
                () {
          if(controller.isLoading.value == true){
            return const Center(child: CircularProgressIndicator());
          }      
           return controller.isError.value
                          ? ErrorCard(
                              controller: controller,
                              retryFunction: () => controller.getEvents(),
                            )
                          : controller.events.isEmpty
                              ? const Text(
                                  "没有可用于定义筛选条件的事件") //TODO: 显示ErrorCard并设置retryFunction:打开事件筛选器(弹出窗口)
                              : ListView.builder(
    ....)})
英文:

> try this

    child: Obx(
            () {
      if(controller.isLoading.value == true){
        return const Center(child: CircularProgressIndicator());
      }      
       return controller.isError.value
                      ? ErrorCard(
                          controller: controller,
                          retryFunction: () =&gt; controller.getEvents(),
                        )
                      : controller.events.isEmpty
                          ? const Text(
                              &quot;There are no events available for the defined filter&quot;) //TODO: Show ErrorCard and set retryFuntion: openFilter of events (popup)
                          : ListView.builder(
....)})

答案4

得分: 0

根据提供的代码,我找不到可能导致该错误的任何错误。

错误提示你需要重建某些东西(可能是controller),因为有些东西已更改(例如属性值已更改),而构建正在构建它。

没有完整的代码,我无法确定错误的来源。然而,你可以尝试将控制器的初始化移出构建方法,如果还没有这样做的话。

希望这对你有所帮助。

final YourController controller = Get.put(YourController());

@override
Widget build(context){
...
}
英文:

From the code given, I couldn't find any error that could cause the said error.

The error is telling you that something (probably controller) has changes (property value has changed for example) and it needs rebuild while the build is building it.

I'm not sure where the source of the error without the full code. However, you may try to move the initialization of the controller out of the build method, if you haven't had.

Hope this help.

final YourController controller = Get.put(YourController());

@override
Widget build(context){
...
}

答案5

得分: 0

你可以在不使用initState的情况下调用控制器,你可以在initState中调用以加载数据。

      initState(){
         super.initState();
         Future.delayed(Duration.zero, () {
            // 写代码
         });
      }
英文:

you may calling controller without initState , you may call to load data in initState

  initState(){
     super.initState();
      Future.delayed(Duration.zero, () {
    // write Code
        });
    }

huangapple
  • 本文由 发表于 2023年2月26日 22:50:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75572777.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定