I have the following problem. When my app starts (user loggs in) I need to read value from firebase which is accountId
- this is id of an account created separately from user account, which is stored in one of the Firestore documents.
After fetching accountId
through FutureBuilder which is nested in main.dart
and I am saving it through
Provider.of<RegistrationHelper>(context.updateAccountId(accountId);
to my class RegistrationHelper
to make it available for other places.
The thing is, that although the accountId
gets saved in RegistrationHelper
, I am getting the following error, you can find at the bottom.
Here is a code of my main.dart
. Does anyone know how to solve this problem?
Many thanks in advance for your support!
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(JustAnApp());
}
class EmotionsApp extends StatelessWidget {
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<RegistrationHelper>(
create: (_) => RegistrationHelper(),
),
ChangeNotifierProvider<EmotionsHelper>(
create: (_) => EmotionsHelper(),
),
],
child: MaterialApp(
title: 'Jak się dziś czujesz?',
theme: ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.orange,
accentColorBrightness: Brightness.light,
canvasColor: Color.fromRGBO(255, 254, 229, 1),
backgroundColor: Colors.deepPurple,
buttonTheme: ButtonTheme.of(context).copyWith(
buttonColor: Colors.purple,
textTheme: ButtonTextTheme.primary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
fontFamily: 'Raleway',
textTheme: ThemeData.light().textTheme.copyWith(
bodyText1: TextStyle(
color: Color.fromRGBO(20, 51, 51, 1),
),
bodyText2: TextStyle(
color: Color.fromRGBO(20, 51, 51, 1),
),
headline1: TextStyle(
fontSize: 20,
fontFamily: 'RobotoCondensed',
fontWeight: FontWeight.bold,
),
),
),
home: FutureBuilder(
future: _initialization,
builder: (context, snapshot) {
if (snapshot.hasError) {
print('Snapshot error (main.dart) : ${snapshot.error}');
return SomethingWentWrong();
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.connectionState == ConnectionState.done) {
// print('Snapshot (main.dart) : ${snapshot.connectionState}');
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, streamSnapshot) {
if (streamSnapshot.data == null) return LoginScreen();
if (streamSnapshot.connectionState ==
ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
if (streamSnapshot.hasData) {
//print('MAIN.DART streamSnapshot data: $streamSnapshot');
final user = FirebaseAuth.instance.currentUser;
return FutureBuilder(
//HERE IS WHERE I AM FETCHING ACCOUNT ID
future: FirebaseFirestore.instance
.collection('root')
.doc('users')
.collection('userData')
.doc(user!.uid)
.get(),
builder: (BuildContext context, AsyncSnapshot snap) {
if (snap.data == null)
return Center(child: CircularProgressIndicator());
if (snap.connectionState == ConnectionState.waiting)
return Center(
child: CircularProgressIndicator(),
);
if (snap.hasData) {
//AND HERE I AM STORING ACCOUNT ID TO REGISTRATION HELPER CLASS
Provider.of<RegistrationHelper>(context)
.updateActualAccountId(
snap.data['accountId']);
//return Text('accountId updated');
}
return FacilitiesScreen();
});
} else {
return LoginScreen();
}
});
}
return Center(child: CircularProgressIndicator());
},
),
routes: {
...
},
),
);
}
}
And a simple method in RegistrationHelper:
void updateActualAccountId(String accountId) {
actualAccountId = accountId;
notifyListeners();
}
Error I am getting:
======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for RegistrationHelper:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<RegistrationHelper> 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: _InheritedProviderScope<RegistrationHelper>
value: Instance of 'RegistrationHelper'
listening to value
The widget which was currently being built when the offending call was made was: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>
dirty
state: _FutureBuilderState<DocumentSnapshot<Map<String, dynamic>>>#bdfb1
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4305:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4320:6)
#2 _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:531:5)
#3 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:308:24)
#4 RegistrationHelper.updateActualAccountId (package:emotions4_flutter/auth/auth_registration_helper.dart:42:5)
#5 _FacilitiesScreenState._updateAccountId (package:emotions4_flutter/screens/facilities_screen.dart:27:10)
#6 _FacilitiesScreenState.build.<anonymous closure> (package:emotions4_flutter/screens/facilities_screen.dart:101:25)
#7 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:782:55)
#8 StatefulElement.build (package:flutter/src/widgets/framework.dart:4782:27)
#9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4665:15)
#10 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11)
#11 Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#12 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:33)
#13 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#14 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
#15 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
#16 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
#17 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5)
#21 _invoke (dart:ui/hooks.dart:166:10)
#22 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5)
#23 _drawFrame (dart:ui/hooks.dart:129:31)
(elided 3 frames from dart:async)
The RegistrationHelper sending notification was: Instance of 'RegistrationHelper'
====================================================================================================
The solution which seems to be working is calling RegistrationHelper method from `didChangeDependencies' from a home screen file (not from main.dart), like this:
@override
void didChangeDependencies() {
Provider.of<RegistrationHelper>(context, listen: false).getAccountId();
super.didChangeDependencies();
}
No errors anymore. Thanks a lot for your help!