使用GETX控制器时在构建过程中调用setState()或markneedsbuild()

发布于 2025-02-11 02:23:51 字数 3737 浏览 1 评论 0 原文

我正在尝试简单地尝试从小部件调用GETX控制器方法。 而且我已经对真实和错误设置了负载。

但是同样的事情在Main.dart首次奏效。当我在这里使用相同的逻辑时,它向我显示了这个错误。

关于这个概念的任何帮助。将不胜感激。

bookcontroller.dart

 getPresentBooksOfStudent({required String USN}) async {
    try {
      isLoading(true);
      http.Response response = await http
          .get(Uri.parse('http://10.0.2.2:3500/booksPendingByUSN/$USN'));

      print(response.body);
      if (response.statusCode == 200) {
        // data successfully
        print("Success in data fetch");
        var result = jsonDecode(response.body);
        logger.i(result);
        sudentBookModel = SudentBookModel.fromJson(result);
      } else {
        print(response.body);
      }
    } catch (e) {
      logger.e(e);                   //// <- Getting error here
    } finally {
      isLoading(false);
    }
  }

transactionscreen.dart

class TransactionListScreen extends StatefulWidget {
  String usn;
  TransactionListScreen({Key? key, required this.usn}) : super(key: key);

  @override
  State<TransactionListScreen> createState() => _TransactionListScreenState();
}

class _TransactionListScreenState extends State<TransactionListScreen> {
  BookController bookController = Get.find();
  @override
  void initState() {
    bookController.getPresentBooksOfStudent(USN: widget.usn);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Obx(() => bookController.isLoading.value
            ? Center(child: CircularProgressIndicator())
            : Padding(
                padding: EdgeInsets.only(top: 20),
                child: ListView.builder(itemBuilder: ((context, index) {
                  return Column(
                    children: [
                      ListTile(
                          title: Text(bookController
                                  .sudentBookModel?.data?[index].bookTitle ??
                              'Book')),
                      const Divider()
                    ],
                  );
                })),
              )));
  }
}

log

I/flutter (18223): | #0   BookController.getPresentBooksOfStudent (package:app/controller/book_controller.dart:98:14)
package:app/controller/book_controller.dart:98
I/flutter (18223): │ #1   _TransactionListScreenState.something (package:app/transactionListScreen.dart:24:26)
package:app/transactionListScreen.dart:24
I/flutter (18223): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter (18223): │ ⛔ setState() or markNeedsBuild() called during build.
I/flutter (18223): │ ⛔ 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.
I/flutter (18223): │ ⛔ The widget on which setState() or markNeedsBuild() was called was:
I/flutter (18223): │ ⛔   Obx
I/flutter (18223): │ ⛔ The widget which was currently being built when the offending call was made was:
I/flutter (18223): │ ⛔   Builder

编辑:我正在寻找有关发生的事情的解释,以及为什么在主屏幕中起作用的原因,为什么不是在这里吗?当您添加以下代码时,这实际上是什么意思:

如@mahi回答

WidgetsBinding.instance
        .addPostFrameCallback((_) 
{
    bookController.getPresentBooksOfStudent(USN: widget.usn);

}

I am trying to make a simple attempt of calling the Getx Controller method from the widget.
And i have set the loading true and false accordingly.

But the same thing worked in the main.dart in the first time. When i am using the same logic here it is showing me this error.

Any help on this concept . Would be greatly appreciated.

BookController.dart

 getPresentBooksOfStudent({required String USN}) async {
    try {
      isLoading(true);
      http.Response response = await http
          .get(Uri.parse('http://10.0.2.2:3500/booksPendingByUSN/$USN'));

      print(response.body);
      if (response.statusCode == 200) {
        // data successfully
        print("Success in data fetch");
        var result = jsonDecode(response.body);
        logger.i(result);
        sudentBookModel = SudentBookModel.fromJson(result);
      } else {
        print(response.body);
      }
    } catch (e) {
      logger.e(e);                   //// <- Getting error here
    } finally {
      isLoading(false);
    }
  }

TransactionScreen.dart

class TransactionListScreen extends StatefulWidget {
  String usn;
  TransactionListScreen({Key? key, required this.usn}) : super(key: key);

  @override
  State<TransactionListScreen> createState() => _TransactionListScreenState();
}

class _TransactionListScreenState extends State<TransactionListScreen> {
  BookController bookController = Get.find();
  @override
  void initState() {
    bookController.getPresentBooksOfStudent(USN: widget.usn);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Obx(() => bookController.isLoading.value
            ? Center(child: CircularProgressIndicator())
            : Padding(
                padding: EdgeInsets.only(top: 20),
                child: ListView.builder(itemBuilder: ((context, index) {
                  return Column(
                    children: [
                      ListTile(
                          title: Text(bookController
                                  .sudentBookModel?.data?[index].bookTitle ??
                              'Book')),
                      const Divider()
                    ],
                  );
                })),
              )));
  }
}

log

I/flutter (18223): | #0   BookController.getPresentBooksOfStudent (package:app/controller/book_controller.dart:98:14)
package:app/controller/book_controller.dart:98
I/flutter (18223): │ #1   _TransactionListScreenState.something (package:app/transactionListScreen.dart:24:26)
package:app/transactionListScreen.dart:24
I/flutter (18223): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter (18223): │ ⛔ setState() or markNeedsBuild() called during build.
I/flutter (18223): │ ⛔ 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.
I/flutter (18223): │ ⛔ The widget on which setState() or markNeedsBuild() was called was:
I/flutter (18223): │ ⛔   Obx
I/flutter (18223): │ ⛔ The widget which was currently being built when the offending call was made was:
I/flutter (18223): │ ⛔   Builder

Edit: I am looking for the explanation of what's happening , and why in the main screen it worked , why not here ? What does this actually mean when you add the below code:

As answered by @Mahi

WidgetsBinding.instance
        .addPostFrameCallback((_) 
{
    bookController.getPresentBooksOfStudent(USN: widget.usn);

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稚然 2025-02-18 02:23:52

在第一步中,以下代码调用并从Initstate中的API下载数据。

 bookController.getPresentBooksOfStudent(USN: widget.usn);

同时,它还构建了您的布局。当数据下载完成 OBX 时,将根据加载值更新UI。

因此,UI没有完成,OBX试图再次更新它。


之所以发生这种情况,是因为您尝试更新构建方法而不允许完成构建方法。

因此,下面的代码在绘画后执行
有关更多详细信息:

WidgetsBinding.instance
        .addPostFrameCallback((_) 
{
    bookController.getPresentBooksOfStudent(USN: widget.usn);

}

In first step, the below code calls and download data from your api in initstate.

 bookController.getPresentBooksOfStudent(USN: widget.usn);

at the same time, it also building your layout. when the data download completes obx will update the UI based on the loading value.

so UI didn't completed and obx tries to update it again.


This is happen because you try to update the build method without allowing to complete the build method.

So below code executes after the painting
for more details: https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html

WidgetsBinding.instance
        .addPostFrameCallback((_) 
{
    bookController.getPresentBooksOfStudent(USN: widget.usn);

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文