I am trying to use firebase analytics to follow the user navigation and pressing on some buttons i made a _currentScreen() function which i call init state in the class in which the user navigates to
here is the function
Future<Null> _currentScreen() async {
await widget.analytics.setCurrentScreen(
screenName: 'second screen view', screenClassOverride: 'SecondScreenView');
}
and i made another function which is _sendAnalytics which i call when the user click on a button; here is the function:
Future<Null> _sendAnalytics() async {
await widget.analytics
.logEvent(name: 'launchhhh', parameters: <String, dynamic>{});
}
I have several problems:
1st- in the initstate in the second screen class it's warning :is method overrides a method annotated as #mustCallSuper in 'State', but does not invoke the overridden method.
2nd- when i run the code and press the button of navigations i have this
[ERROR:flutter/shell/common/shell.cc(181)] Dart Error: Unhandled exception:
E/flutter (12744): NoSuchMethodError: The method 'logEvent' was called on null.
E/flutter (12744): Receiver: null
E/flutter (12744): Tried calling: logEvent(name: "launchhhh", parameters: _LinkedHashMap len:0)
E/flutter (12744): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
E/flutter (12744): #1 FirstScreenState._sendAnalytics (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:40:10)
3- Also, when i comment the _sendanalytics function
NoSuchMethodError: The method 'setCurrentScreen' was called on null.
E/flutter (15612): Receiver: null
E/flutter (15612): Tried calling: setCurrentScreen(screenClassOverride: "SecondScreenView", screenName: "second screen view")
E/flutter (15612): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
E/flutter (15612): #1 SecondScreenState._currentScreen (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:91:28)
E/flutter (15612): <asynchronous suspension>
E/flutter (15612): #2 SecondScreenState.initState (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:88:5)
E/flutter (15612): #3 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3787:58)
E/flutter (15612): #4 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3653:5)
I don't know where is the problem any help? and here is my whole code:
import 'package:flutter/material.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_analytics/observer.dart';
import 'dart:async';
class MyAppf extends StatelessWidget {
static FirebaseAnalytics analytics = new FirebaseAnalytics();
static FirebaseAnalyticsObserver observer =
new FirebaseAnalyticsObserver(analytics: analytics);
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
navigatorObservers: <NavigatorObserver>[observer],
// home: new WallScreen(analytics: analytics, observer: observer),
home: new FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
FirstScreen({this.analytics, this.observer});
#override
FirstScreenState createState() => new FirstScreenState();
}
class FirstScreenState extends State<FirstScreen> {
Future<Null> _sendAnalytics() async {
await widget.analytics
.logEvent(name: 'launchhhh', parameters: <String, dynamic>{});
}
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
FirstScreenState({this.analytics, this.observer});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
_sendAnalytics();
},
),
),
);
}
}
class SecondScreen extends StatefulWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
SecondScreen({this.analytics, this.observer});
#override
SecondScreenState createState() => new SecondScreenState();
}
class SecondScreenState extends State<SecondScreen> {
#override
void initState() {
_currentScreen();
}
Future<Null> _currentScreen() async {
await widget.analytics.setCurrentScreen(
screenName: 'second screen view', screenClassOverride: 'SecondScreenView');
}
Future<Null> _sendAnalyticsback() async {
await widget.analytics
.logEvent(name: 'back', parameters: <String, dynamic>{});
}
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
SecondScreenState({this.analytics, this.observer});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
_sendAnalyticsback();
},
child: Text('Go back!'),
),
),
);
}
}
EDIT I passed my var analytics to Widgets to be
home:new FirstScreen(analytics: analytics),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen(analytics:analytics)),
instead of :
home:new FirstScreen(),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
But still it's the same error calling on null
You need to pass your var analytics to your Widgets.
new FirstScreen(),
new SecondScreen(),
Should be :
new FirstScreen(analytics: analytics),
new SecondScreen(analytics: analytics),
Do not use static members as they are intended to be accessed through the class itself. A cealner way of what you are trying to do is declare MyApp as a SatetfulWidget , now you analytics and observer can be private members of State class and use initState to initialize them, see the following example:
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
FirebaseAnalytics _analytics;
FirebaseAnalyticsObserver _observer ;
#override
void initState() {
_analytics = FirebaseAnalytics();
_observer = FirebaseAnalyticsObserver(analytics: _analytics);
super.initState();
}
#override
Widget build(BuildContext context) {
return Container();
}
}
If you want to keep your widget Stateless you can initialize your observer in the constructor's initializer list, this requires the analytics field to be passed a value when MyApp is created MyApp(analytics:FirebaseAnalytics()):
class MyApp extends StatelessWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
MyApp({Key key,#required this.analytics})
: observer = FirebaseAnalyticsObserver(analytics: analytics),
super(key: key);
#override
Widget build(BuildContext context) {
return Container();
}
}
Related
this error "
"The getter 'uid' was called on null.Receiver: nullTried calling: uid"
I Faced when i try to sign out from any screen "except home screen" ,
is there any solution for this problem ??
Wrapper :
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User_fb>(context);
// return home or login
if (user == null) {
return Login();
} else {
print(user.uid);
return Home();
}
}
}
auth :
Future Signinwithemailandpassword(var Res_email,var Res_Password) async{
try{
UserCredential result= await _auth.signInWithEmailAndPassword(email: Res_email, password: Res_Password);
User user = result.user;
return _userfromfirebase(user);
}catch(e){
return null;
}
}
Future signOut () async{
try{
return await _auth.signOut();
}
catch(e){
print(e.toString());
print("error at signOut ");
return null;
}
}
main :
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(Main());
}
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
#override
Widget build(BuildContext context) {
return StreamProvider<User_fb>.value(
value: Authservice().user,
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color.fromRGBO(255, 255, 255, 1),
shadowColor: Colors.transparent,
highlightColor: Colors.transparent),
home: Wrapper(),
),
);
}
}
Sign-out button :
ListTile(
leading: Icon(Ionicons.log_out_outline,
color: Color.fromRGBO(86, 197, 150, 1)),
title: Text('Log out'),
onTap: () async {
await _auth.signOut();
},
),
console :
======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building Br(dirty, dependencies: [_InheritedProviderScope<User_fb>], state: _QrState#24e19):
The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
The relevant error-causing widget was:
Qr file:///G:/AndroidStudioProjects/facem/lib/Screens/Home/Home.dart:687:67
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _QrState.build (package:my_compound/Screens/Qr/qr.dart:99:45)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4691:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4746:11)
...
this happens because user is null, So use null check operator.
something like this user?.uid or user.uid ?? '',
TIP: Alway use dart null safety when using flutter.
I'm new to flutter and I just learned how to use isolates in Dart. When I try to access shared preference via an isolate it throws the given below error. This error also appears when I try to access Firebase analytics and remote config. How can I resolve this issue and access SharedPreference, FirebaseRemote config, FirebaseFirestore inside an isolate?
[ERROR:flutter/runtime/dart_isolate.cc(882)] Unhandled exception:
E/flutter (23694): ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
E/flutter (23694): If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
E/flutter (23694): If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
E/flutter (23694): #0 defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:92:7)
E/flutter (23694): #1 defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:105:4)
E/flutter (23694): #2 MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:143:62)
E/flutter (23694): #3 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:149:36)
E/flutter (23694): #4 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:332:12)
E/flutter (23694): #5 MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:359:49)
E/flutter (23694): #6 MethodChannelSharedPreferencesStore.getAll (package:shared_preferences_platform_interface/method_channel_shared_preferences.dart:54:22)
E/flutter (23694): #7 SharedPreferences._getSharedPreferencesMap (package:shared_preferences/shared_preferences.dart:191:57)
E/flutter (23694): #8 SharedPreferences.getInstance (package:shared_preferences/shared_preferences.dart:58:19)
E/flutter (23694): #9 _wraperState.islt (package:spynett/main.dart:122:55)
E/flutter (23694): <asynchronous suspension>
E/flutter (23694): #10 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:304:17)
E/flutter (23694): #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await setupLocator();
runApp(MyApp());
}
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
startinitsetup();
});
}
Future startinitsetup() async{
debugPrint('Calling setup');
await _dynamiclink.handledynamiclink();
await _pushNotificationService.initilalise();
await _remoteConfigService.initialise();
ReceivePort reciveport = ReceivePort();
Isolate.spawn(islt, reciveport.sendPort);
SendPort childSendPort = await reciveport.first;
ReceivePort responceport = ReceivePort();
childSendPort.send(['message',responceport.sendPort]);
await responceport.first;
}
static Future<int> islt(SendPort mainSendPort) async{
ReceivePort childRecivePort = ReceivePort();
mainSendPort.send(childRecivePort.sendPort);
await for (var message in childRecivePort){
SendPort replyport = message[1];
SharedPreferences _pref = await SharedPreferences.getInstance();
replyport.send('done');
}
}
You can copy paste run full code below
To use SharedPreferences in Isolate, you can use package https://pub.dev/packages/flutter_isolate
You can change from
Isolate.spawn(islt, reciveport.sendPort);
to
FlutterIsolate.spawn(islt, reciveport.sendPort);
output of full test code
I/flutter (12689): Calling setup
...
I/flutter (12689): test test
I/flutter (12689): isolate when msg recived
I/flutter (12689): reply done
full test code
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_isolate/flutter_isolate.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
//await Firebase.initializeApp();
//await setupLocator();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
startinitsetup();
});
}
Future startinitsetup() async {
debugPrint('Calling setup');
ReceivePort reciveport = ReceivePort();
FlutterIsolate.spawn(islt, reciveport.sendPort);
SendPort childSendPort = await reciveport.first;
ReceivePort responceport = ReceivePort();
childSendPort.send(['message', responceport.sendPort]);
String reply = await responceport.first;
print("reply $reply");
}
static Future<int> islt(SendPort mainSendPort) async {
ReceivePort childRecivePort = ReceivePort();
mainSendPort.send(childRecivePort.sendPort);
await for (var message in childRecivePort) {
SendPort replyport = message[1];
SharedPreferences _pref = await SharedPreferences.getInstance();
await _pref.setString("yourKey", "test");
String testPref = _pref.get("yourKey");
print("test $testPref");
debugPrint('isolate when msg recived');
replyport.send('done');
}
}
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
The error received:
NoSuchMethodError: invalid member on null: 'collection'
I'm using the Flutter Provider Package 4.3.2+2 for complex state management.
I get my data from Firebase, this is the data structure:
This is the provider class:
class ClientsProvider extends ChangeNotifier {
FirebaseFirestore _fs;
StreamSubscription<QuerySnapshot> _stream;
List<QueryDocumentSnapshot> clients = [];
ClientsProvider() {
_stream = _fs.collection("clients").snapshots().listen((event) {//THIS IS WHERE THE ERROR POINTS
clients = event.docs;
notifyListeners();
});
}
#override
void dispose() {
super.dispose();
_stream.cancel();
}
}
This is the parent widget:
class _ParentState extends State<Parent> {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<ClientsProvider>(
create: (context) => ClientsProvider()),
ChangeNotifierProvider<MyProvider>(
create: (context) => MyProvider()),
],
child: Dashboard(),//This widget contains the Child() widget two widgets down.
);
}
}
This is the child widget that needs to be updated when the firebase snapshot updates:
class _ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return Column(
children: [
_buildAddNew(),
Consumer<ClientsProvider>(
builder: (context, clientProvider, child) {
return Container(child: Text(clientProvider.clients.toString()));
},
),
],
);
}
}
Once again, the error received:
NoSuchMethodError: invalid member on null: 'collection'
The data isn't null, why am I receiving this error?
_fs is null because you never assigned it. Perhaps you meant to do this, as shown in the documentation:
FirebaseFirestore _fs = FirebaseFirestore.instance;
Have anybody encounter this issue before?
E/flutter (12975): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Looking up a deactivated widget's ancestor is unsafe.
E/flutter (12975): At this point the state of the widget's element tree is no longer stable.
E/flutter (12975): To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
Upon googling I found out that it has something to do with context? That is why I passed the context via argument of a function
Below is the code
class CustRegView extends StatefulWidget {
#override
_CustRegViewState createState() => _CustRegViewState();
}
class CustRegView extends StatelessWidget{
final TextEditingController _controller = TextEditingController();
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return BaseView<CustRegViewModel>(
builder: (context, model, child) => Scaffold(
...<some code>
FlatButton (
onPressed: () async {
var registerSuccess = await model.register( _controller.text);
if (registerSuccess) {
Navigator.pushNamed(context, 'newScreen'); <--- E R R O R H E R E } else {
UIHelper().showErrorButtomSheet(context, model.errorMessage);
}
)
}
CustRegViewModel looks like this
class CustRegViewModel extends BaseViewModel {
final AuthService _authService = locator<AuthService>();
final DialogService _dialogService = locator<DialogService>();
dynamic verifiedUserID ;
Future<bool> register(String phoneNo) async {
verifiedUserID = await verifyPhone(updatedPhoneNo);
return verifiedUserID != null ? true : false; // From here it
// returns true
}
Future<void> verifyPhone(phoneNo) async {
var completer = Completer<dynamic>();
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: updatedPhoneNo,
timeout: Duration(seconds: 50),
verificationCompleted: (AuthCredential authCred) async {...... <some code>
verificationFailed: (AuthException authException) {...... <some code>
codeSent: (String verID, [int forceCodeResend]) async {...... <some code>
codeAutoRetrievalTimeout: (String verID) {...
).catchError((error) {...... <some code>
return completer.future;
}
}
main class looks like this
void main() {
setupLocator();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final GlobalKey<NavigatorState> navigatorKey =
new GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return StreamProvider<User>(
initialData: User.initial(),
create: (BuildContext context) => locator<AuthService>().user,
child: MaterialApp(
builder: (context, widget) => Navigator(
onGenerateRoute: (settings) => MaterialPageRoute(
builder: (context) => DialogManager(
child: widget,
),
),
),
title: 'Fitness Diet',
theme: ThemeData(),
initialRoute: 'splash',
navigatorKey: navigatorKey,
onGenerateRoute: Router.generateRoute,
),
);
}
}
I'm trying to build a flutter app for the first time and I'm having a lot of trouble to get it done. I'm having problem especially with asynchronous coding. I have a persistent bottom nav bar for the home of a page. What I want from the Form nab button is to check if the logged in user already fill up a form or not. If the user didnt fill out the form, then I want to show DonorFormHomeBefore() and if the user already filled out the form then whenever pressed to the Form from nav bar, I want to show DonorFormHomeAfter(). To implement this, I used a wrapper and tried to get database instance from firebase. But, instead of fetching the data from firebase, the code runs the later part of the codes and causing error.
class DonorHome extends StatelessWidget {
final DonorAuthService _auth = DonorAuthService();
final PersistentTabController _controller = PersistentTabController(initialIndex: 0);
List<Widget> _buildScreens() {
return [
DonorRequests(),
DonorProfile(),
DonorFormWrapper(),
];
}
.....
class DonorAuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
//get database instance
Future getDatabaseInstance(String uid) async{
/*await Firestore.instance.collection("Donor Lists").document(uid).get().then((value) {
print(value.data);
return value.data;
});*/
final value = await Firestore.instance.collection('Donor Lists').document(uid).get();
print(value.data);
return value.data;
}
class DonorFormWrapper extends StatefulWidget{
#override
_DonorFormWrapperState createState() => _DonorFormWrapperState();
}
class _DonorFormWrapperState extends State<DonorFormWrapper>{
bool before;
#override
Widget build (BuildContext context) {
final DonorAuthService _auth = DonorAuthService();
final user = Provider.of<DonorUser>(context);
print(user.uid);
dynamic x = _auth.getDatabaseInstance(user.uid);
print(x);
if (x['name'] == 'name') {
before = true;
print(before);
return DonorFormHomeBefore();
}
else {
before = false;
print(before);
return DonorFormHomeAfter();
}
//print('before');
//print(before);
/*if (before == true || before == null) {
return DonorFormHomeBefore();
}
else if(before == false) {
return DonorFormHomeAfter();
} */
/*return Container(
height: 0.0, width: 0.0,
);*/
}
}
Here before it's fetching data and return that into "x", its running to to later portion of the code and getting a error of this:
Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building DonorFormWrapper(dirty, dependencies: [_InheritedProviderScope<DonorUser>], state: _DonorFormWrapperState#a1b86):
Class 'Future<dynamic>' has no instance method '[]'.
Receiver: Instance of 'Future<dynamic>'
Tried calling: []("name")
The relevant error-causing widget was
DonorFormWrapper
lib\…\Home\donor_home.dart:21
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _DonorFormWrapperState.build
package:PlasmaBank/…/Home/donor_form_wrapper.dart:33
#2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4619
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502
#4 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4675
...
After using this code
class DonorFormWrapper extends StatefulWidget{
#override
_DonorFormWrapperState createState() => _DonorFormWrapperState();
}
class _DonorFormWrapperState extends State<DonorFormWrapper>{
Future<dynamic> _initUserFuture;
bool before;
#override
void initState() {
super.initState();
final DonorAuthService _auth = DonorAuthService();
final user = Provider.of<DonorUser>(context);
print(user.uid);
_initUserFuture = _auth.getDatabaseInstance(user.uid);
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initUserFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data['name'] == 'name') {
before = true;
print(before);
return DonorFormHomeBefore();
} else {
before = false;
print(before);
return DonorFormHomeAfter();
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}
This is the error I got
Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building DefaultTextStyle(debugLabel: (englishLike body1 2014).merge(blackMountainView bodyText2), inherit: false, color: Color(0xdd000000), family: Roboto, size: 14.0, weight: 400, baseline: alphabetic, decoration: TextDecoration.none, softWrap: wrapping at box width, overflow: clip):
dependOnInheritedWidgetOfExactType<_InheritedProviderScope<DonorUser>>() or dependOnInheritedElement() was called before _DonorFormWrapperState.initState() completed.
When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.
Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.
The relevant error-causing widget was
PersistentTabView
lib\…\Home\donor_home.dart:68
When the exception was thrown, this was the stack
#0 StatefulElement.dependOnInheritedElement.<anonymous closure>
package:flutter/…/widgets/framework.dart:4761
#1 StatefulElement.dependOnInheritedElement
package:flutter/…/widgets/framework.dart:4804
#2 Provider.of
package:provider/src/provider.dart:213
#3 _DonorFormWrapperState.initState
package:PlasmaBank/…/Home/donor_form_wrapper.dart:26
#4 StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:4640
...
Here is the error I'm getting from my emulator
import 'package:flutter/material.dart';
class DonorFormHomeAfter extends StatefulWidget {
#override
_DonorFormHomeAfterState createState() => _DonorFormHomeAfterState();
}
class _DonorFormHomeAfterState extends State<DonorFormHomeAfter> {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Data has been saved!'),
),
);
}
}
import 'package:PlasmaBank/screens/Donor/Home/donor_home_form.dart';
import 'package:flutter/material.dart';
class DonorFormHomeBefore extends StatefulWidget {
#override
_DonorFormHomeBeforeState createState() => _DonorFormHomeBeforeState();
}
class _DonorFormHomeBeforeState extends State<DonorFormHomeBefore> {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: RaisedButton(
child: Text('Create New Donor'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DonorForm()),
);
},
),
),
);
}
}
class DonorWrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<DonorUser>(context);
print(user);
// return either the Home or Authenticate widget
if (user == null){
return DonorAuthenticate();
} else {
return DonorHome();
}
}
}
Code works fine right now except, whenever I press the Form button from the nav bar, there comes an error for a blink of a second and the error goes away immediately. Here is the details:
class DonorFormWrapper extends StatefulWidget{
#override
_DonorFormWrapperState createState() => _DonorFormWrapperState();
}
class _DonorFormWrapperState extends State<DonorFormWrapper>{
bool before;
#override
Widget build(BuildContext context) {
final DonorAuthService _auth = DonorAuthService();
final user = Provider.of<DonorUser>(context);
return FutureBuilder(
future: _auth.getDatabaseInstance(user.uid),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot){
if(snapshot.data['name']== 'name') {
return DonorFormHomeBefore();
}
else if (snapshot.data['name'] != 'name') {
return DonorFormHomeAfter();
}
else {
return Center(
child: CircularProgressIndicator(
),
);
}
}
);
}
}
Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building FutureBuilder<dynamic>(dirty, state: _FutureBuilderState<dynamic>#f8ba4):
The method '[]' was called on null.
Receiver: null
Tried calling: []("name")
The relevant error-causing widget was
FutureBuilder<dynamic>
package:PlasmaBank/…/Home/donor_form_wrapper.dart:32
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _DonorFormWrapperState.build.<anonymous closure>
package:PlasmaBank/…/Home/donor_form_wrapper.dart:35
#2 _FutureBuilderState.build
package:flutter/…/widgets/async.dart:732
#3 StatefulElement.build
package:flutter/…/widgets/framework.dart:4619
#4 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502
...
Please check if the snapshot has data before performing any action.
import 'package:flutter/material.dart';
class DonorFormWrapper extends StatefulWidget {
#override
_DonorFormWrapperState createState() => _DonorFormWrapperState();
}
class _DonorFormWrapperState extends State<DonorFormWrapper> {
#override
Widget build(BuildContext context) {
final DonorAuthService _auth = DonorAuthService();
final user = Provider.of<DonorUser>(context);
return FutureBuilder(
future: _auth.getDatabaseInstance(user.uid),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData && snapshot.data != null) {
if (snapshot.data['name'] == 'name') {
return DonorFormHomeBefore();
}
return DonorFormHomeAfter();
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
}
}
When I test with making your code short, it works well. It seems that the problem is located other source. DonorFormHomeBefore() or DonorFormHomeAfter()
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "landRegistration App",
theme: new ThemeData(primarySwatch: Colors.amber),
home: DonorFormWrapper(),
);
}
}
class DonorFormWrapper extends StatefulWidget {
#override
_DonorFormWrapperState createState() => _DonorFormWrapperState();
}
class _DonorFormWrapperState extends State<DonorFormWrapper> {
Future<dynamic> _initUserFuture;
bool before;
#override
void initState() {
super.initState();
_initUserFuture = getTest();
}
Future<dynamic> getTest() async {
return await Future.value(42).timeout(const Duration(seconds: 3));
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initUserFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot.data);
if (snapshot.data == 42) {
before = true;
print(before);
return Container(child: Text('1'));
} else {
before = false;
print(before);
return Container(child: Text('2'));
}
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}