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