Hello guys am trying to sign in to my flutter app but I keep on getting the error:
Sign In Error: type 'Null' is not a subtype of type '_StateDataWidget' in type cast,
I used the flutter authentication example in git here is the link: https://github.com/delay/flutter_firebase_auth_example,
Here is the code to my login form that contains the signIn function:
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
// ignore: import_of_legacy_library_into_null_safe
// import 'package:flushbar/flushbar.dart';
import '/components/authentication/util/auth.dart';
import '/components/authentication/util/validator.dart';
import '/components/authentication/util/state_widget.dart';
import '/components/authentication/authpages/accesspages/auth_loading_screen.dart';
class LoginForm extends StatefulWidget {
const LoginForm({Key? key}) : super(key: key);
@override
_LoginFormState createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final GlobalKey<FormState> _loginFormKey = GlobalKey<FormState>();
late TextEditingController _emailController;
late TextEditingController _passwordController;
bool _autoValidate = false;
bool _loadingVisible = false;
@override
void initState() {
_emailController = new TextEditingController();
_passwordController = new TextEditingController();
super.initState();
}
bool _obscureText = true;
// ignore: unused_element
void _toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
Widget build(BuildContext context) {
final emailField = TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
validator: (value) => Validator.validateEmail(value!),
// ignore: deprecated_member_use
cursorColor: Theme.of(context).cursorColor,
// initialValue: '@gmail.com',
maxLength: 40,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
labelText: 'Email:',
labelStyle: TextStyle(color: Colors.red, fontSize: 20),
helperText: 'Enter Your Email',
helperStyle: TextStyle(color: Colors.black, fontSize: 15),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red.shade600),
),
),
);
final passwordField = TextFormField(
controller: _passwordController,
obscureText: _obscureText,
validator: (value) => Validator.validatePassword(value!),
// ignore: deprecated_member_use
cursorColor: Theme.of(context).cursorColor,
maxLength: 40,
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
labelText: 'Password:',
labelStyle: TextStyle(color: Colors.red, fontSize: 20),
helperText: 'Enter Your Password',
helperStyle: TextStyle(color: Colors.black, fontSize: 15),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red.shade600),
),
suffixIcon: IconButton(
icon: Icon(
_obscureText ? Icons.visibility : Icons.visibility_off,
),
onPressed: _toggle,
color: Colors.red,
),
),
);
final loginButton = ElevatedButton(
child: Text(
"login",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 18.0,
color: Colors.white,
),
),
onPressed: () {
_signIn(
context: context,
email: _emailController.text,
password: _passwordController.text);
// Navigator.pushNamed(context, '/Home');
},
style: ElevatedButton.styleFrom(
primary: Colors.red,
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
),
);
final passwordResetLink = InkWell(
child: Text(
"Forgot Password?",
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
onTap: () {
Future.delayed(Duration.zero, () {
Navigator.pushNamed(context, '/Reset');
});
},
);
final registrationLink = InkWell(
child: Text(
"Registered? Sign Up",
style: TextStyle(
color: Colors.red,
fontSize: 25,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
onTap: () {
Future.delayed(Duration.zero, () {
Navigator.pushNamed(context, '/Registration');
});
},
);
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
height: MediaQuery.of(context).size.height,
child: ListView(
children: [
Ink(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/loginimage.jpg'),
fit: BoxFit.cover,
),
),
child: Container(
color: Colors.black.withOpacity(0.1),
padding: const EdgeInsets.all(40.0),
child: AuthLoadingScreen(
child: Form(
key: _loginFormKey,
// ignore: deprecated_member_use
autovalidate: _autoValidate,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"LOGIN",
style: TextStyle(
color: Colors.red.shade600,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 10.0),
//EMAIL FIELD
emailField,
const SizedBox(
height: 10,
),
//PASSWORD FIELD
passwordField,
const SizedBox(height: 20.0),
//LOGIN BUTTON
loginButton,
const SizedBox(height: 10.0),
//PASSWORD RESET LINK
passwordResetLink,
const SizedBox(height: 10.0),
//REGISTRATION LINK
registrationLink,
const SizedBox(height: 100.0),
],
),
),
inAsyncCall: _loadingVisible,
offset: Offset.infinite,
),
),
),
const SizedBox(height: 10.0),
SizedBox(
height: 50,
width: 50,
child: Image.asset('assets/icons/logoicon.jpeg')),
const SizedBox(height: 10.0),
Text(
'Company',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 20.0,
color: Colors.red.shade900,
),
),
],
),
),
);
}
Future<void> _changeLoadingVisible() async {
setState(() {
_loadingVisible = !_loadingVisible;
});
}
void _signIn(
{required String email,
required String password,
BuildContext? context}) async {
if (_loginFormKey.currentState!.validate()) {
try {
SystemChannels.textInput.invokeMethod('TextInput.hide');
await _changeLoadingVisible();
//need await so it has chance to go through error if found.
await StateWidget.of(this.context).logInUser(email, password);
await Navigator.pushNamed(this.context, '/Home');
} catch (error) {
_changeLoadingVisible();
print("Sign In Error: $error");
// ignore: unused_local_variable
String exception = Auth.getExceptionText(Exception(error));
showDialog(
context: this.context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Auth Exception!"),
content: Text("${exception} \n\n ${error}"),
actions: <Widget>[
Row(
children: [
ElevatedButton(
child: Text("close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
)
],
);
});
}
;
} else {
setState(() => _autoValidate = true);
}
}
}
Here is the code to the widget state file:
import 'auth.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import '/models/state.dart';
import '/models/user_model.dart';
import '/models/user_settings.dart';
class StateWidget extends StatefulWidget {
final StateModel state;
final Widget child;
StateWidget({
required this.child,
required this.state,
});
// Returns data of the nearest widget _StateDataWidget
// in the widget tree.
static _StateWidgetState of(BuildContext context) {
return (context.dependOnInheritedWidgetOfExactType<_StateDataWidget>()
as _StateDataWidget)
.data;
}
@override
_StateWidgetState createState() => new _StateWidgetState();
}
class _StateWidgetState extends State<StateWidget> {
late StateModel state;
//GoogleSignInAccount googleAccount;
//final GoogleSignIn googleSignIn = new GoogleSignIn();
@override
void initState() {
super.initState();
if (widget.state != null) {
state = widget.state;
} else {
state = new StateModel(firebaseUserAuth: this.state.firebaseUserAuth, user: this.state.user, userSettings: this.state.userSettings);
initUser();
}
}
Future<Null> initUser() async {
//print('...initUser...');
String firebaseUserAuth = await Auth.getCurrentFirebaseUser();
UserModel? userModel = await Auth.getUserLocal();
UserSettings? settings = await Auth.getSettingsLocal();
setState(() {
state.isLoading = false;
state.firebaseUserAuth = firebaseUserAuth as User;
state.user = userModel as User;
state.userSettings = settings!;
});
}
Future<void> logOutUser() async {
await Auth.signOut();
String firebaseUserAuth = await Auth.getCurrentFirebaseUser();
setState(() {
state.user = this.state.user;
state.userSettings = this.state.userSettings;
state.firebaseUserAuth = firebaseUserAuth as User;
});
}
Future<void> logInUser(email, password) async {
String userId = await Auth.signIn(email, password);
UserModel? userModel = await Auth.getUserFirestore(userId);
await Auth.storeUserLocal(userModel!);
UserSettings? userSettings = await Auth.getSettingsFirestore(userId);
await Auth.storeSettingsLocal(userSettings!);
await initUser();
}
@override
Widget build(BuildContext context) {
return new _StateDataWidget(
// key: null,
data: this,
child: widget.child,
);
}
}
class _StateDataWidget extends InheritedWidget {
final _StateWidgetState data;
_StateDataWidget({
// Key? key,
required Widget child,
required this.data,
}) : super(
// key: key,
child: child
);
// Rebuild the widgets that inherit from this widget
// on every rebuild of _StateDataWidget:
@override
bool updateShouldNotify(_StateDataWidget old) => true;
}
The rest of the files are on the link provided above from the git example since I haven't changed much form them.