Home > Back-end >  setState() or markNeedsBuild() called during build when using the GetX controller
setState() or markNeedsBuild() called during build when using the GetX controller

Time:06-27

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);

}

CodePudding user response:

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);

}

  • Related