ISSUE/BUG :
My flutter app is throwing setState() or markNeedsBuild() called during build error only when I open the profile Page as a deep link ( I am using go_router: ^13.0.1 ) .
NOTE :
- If I Switch to any of the pages normally ( if not from deep link ) it’s not throwing any errors at all .
- Even this Error is occurring only 1 time (i.e if I visit profile_page or home_page again it’s not throwing any error ) The place of occurrence of this bug is profile page and home page( both of these pages are in the PageView of NavBar )
I Tried adding WidgetsBinding.instance.addPostFrameCallback to the initState of profile page but getting the following error :
_TypeError (Null check operator used on a null value)
And even this can be achievable with the proper null safety , we are getting the same exception in the home page as well. So, I am not able to understand the root cause of the main Error .
Compete error ( DEBUG CONSOLE ) :
E/flutter ( 4803): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: setState() or markNeedsBuild() called during build.
E/flutter ( 4803): 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.
E/flutter ( 4803): The widget on which setState() or markNeedsBuild() was called was:
E/flutter ( 4803): Obx
E/flutter ( 4803): The widget which was currently being built when the offending call was made was:
E/flutter ( 4803): PopScope
This is the profile_page.dart
class ProfilePage extends StatefulWidget {
final bool isSelf;
final bool fromOtherPage;
final GetUserModel? user;
ProfilePage(
{super.key, required this.isSelf, this.user, this.fromOtherPage = true})
: assert(
isSelf ? true : user != null,
) {
..
//GetX controllers
..
}
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage>
with SingleTickerProviderStateMixin {
.
.
Future<void> setUserModel() async {
if (widget.isSelf) {
userController.isLoading(true);
GetUserModel newUserModel = await UserServices().getUserByInfoId(
Get.find<CacheManager>().getNewUser().userInfoData!.userInfoId!);
userController.getUserModelByReference(newUserModel);
userController.isLoading(false);
} else {
userController.getUserModelByReference(widget.user!);
}
}
HomeController homeController = Get.find();
@override
initState() {
super.initState();
setUserModel();
final pushNotificationsController =
Get.put(PushNotificationsController());
pushNotificationsController.checkPushNotificationEnabled();
}
Future<void> getUserPolls() async {
await Future.delayed(const Duration(milliseconds: 300));
try {
await homeController.getUserPolls(
userController.userModel.value.userInfoData!.userInfoId!);
} catch (e) {
rethrow;
}
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
final ShowConnectionButtons showButton =
ShowConnectionButtons(userController: userController);
return Obx(
() => userController.isLoading.value
? const LoadingAnimation()
: PopScope(
canPop: true,
onPopInvoked: (didPop) async {
homeController.userPolls.clear();
return;
},
child: SafeArea(
child: Scaffold(
appBar: widget.fromOtherPage
? JustPollAppBar(
shareText:
"Join the opinion-sharing party on JustPoll. Explore this profile at:\nhttps://justpoll.app${RoutesConstants.user}/${userController.userModel.value.userInfoData!.userName!}",
showShareButton: widget.isSelf ? false : true,
size: size,
title:
"@${userController.userModel.value.userInfoData!.userName!}",
)
: null,
body: SingleChildScrollView(
child: Column(
children: [
InkWell(
onTap: () async {
BlocStreamContoller controller =
BlocStreamContoller();
final goRouterState = GoRouter.of(context);
goRouterState.canPop();
widget.isSelf
? profileSettings(
context,
controller,
)
: null;
},
child: Hero(
tag: userController
.userModel.value.userInfoData!.userName ??
'',
.
.
}
}
switchPage function in the home_controller.dart ( The method used to Switch pages and handle refresh ) :
void switchPage(int i) {
previousIndex = index;
if (index == 0 && i == 0) {
if ((homeListController.page ?? 0) > 0) {
if (homeListController.hasClients) {
homeListController.animateToPage(
0,
duration: const Duration(milliseconds: 100),
curve: Curves.ease,
);
}
if (kDebugMode) {
print("Switching to page 1");
}
cacheManager.clearPollBox();
refreshIndicatorState.currentState?.show();
} else {
if (kDebugMode) {
print("Switching to page 0");
}
refreshIndicatorState.currentState?.show();
}
} else {
_index.value = i;
}
update(['Home']);
}
What might be the root cause of this? Because, As I explained the app is throwing the mentioned Exception only when I open the page as a deep link. Anyone please help me out with it?
Got the solution.
I made a silly mistake. I was using
ctx!.push(RoutesConstants.home)while the profile page was already building so I was getting that error.Now, I have replaced it with
ctx!.pushReplacement(RoutesConstants.home)and its working fine now.Thanks :)