Future<void>.value(); - flutter

Im having an issue while running the app. after initializing the app I couldnt properly see the screen at the same tiem there was an error shows which is **Future.value(); inside the feedback.dart. I have tried to catch any error which I have added but I couldnt find any.
I have seen many solution also tried but didnt worked out. Can I anyone please Let me know error which I showed below.
This is loginPage file:
import 'package:flutter/material.dart';
import 'package:food_app/bottombar/screenA.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
#override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
static Future<User?>loginUsingEmailPassword({required String email, required String password, required BuildContext context}) async {
FirebaseAuth auth = FirebaseAuth.instance;
User? user;
try {
UserCredential userCredential = await auth.signInWithEmailAndPassword(email: email, password: password);
user = userCredential.user;
} on FirebaseAuthException catch (e) {
if(e.code == "user not found"){
print("No User found for that email");
}
}
return user;
}
#override
Widget build(BuildContext context) {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
return Scaffold(
appBar: AppBar(
title: const Text("Hello world"),
),
body: SizedBox(
height: 400.0,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
controller: emailController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Username",
),
),
),
const SizedBox(
height: 20.0,
),
Padding(
padding: const EdgeInsets.all(15.0),
child: TextFormField(
controller: passwordController,
obscureText: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Password",
),
),
),
const SizedBox(
height: 20.0,
),
ElevatedButton(
onPressed: () async{
User? user = await loginUsingEmailPassword(email: emailController.text, password: passwordController.text, context: context);
print(user);
if (user != null) {
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => const ScreenA()));
}
},
child: const Text("Login")),
],
),
),
);
}
}
And this is the main.dart file:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:food_app/loginpage.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<FirebaseApp> _initializeFirebase() async {
FirebaseApp firebaseApp = await Firebase.initializeApp();
return firebaseApp;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initializeFirebase(),
builder: (context, snapshot){
if(snapshot.connectionState == ConnectionState.done) {
return const LoginPage();
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
);
}
}
And my error is :
context.findRenderObject()!.sendSemanticsEvent(const TapSemanticEvent());
switch (_platform(context)) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
return SystemSound.play(SystemSoundType.click);
case TargetPlatform.iOS:
case TargetPlatform.linux:
case TargetPlatform.macOS:
case TargetPlatform.windows:
return Future<void>.value();
}
}

Related

Assistance needed with flutter app saving user authentication status

I have an app where Users can currently log in (using phone auth) and log out from the home screen. But whenever the app gets refreshed the user logs out automatically.
What I want to do is to keep the user logged in till he pressed the log out button.
Since I am new to flutter and coding in general it would be helpful if you can help me with the exact code.
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'login.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Firebase.initializeApp();
runApp(const MaterialApp(
home: MyApp(),
debugShowCheckedModeBanner: false,
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return const LoginScreen();
}
}
login.dart
import 'package:flutter/material.dart';
import 'otp.dart';
import 'package:intl_phone_field/intl_phone_field.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
String Country = '';
final TextEditingController _controller2 = TextEditingController();
final TextEditingController _controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Phone Auth'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(children: [
Container(
margin: const EdgeInsets.only(top: 60),
child: const Center(
child: Text(
'Phone Authentication',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 28),
),
),
),
//Phone feild
IntlPhoneField(
decoration: const InputDecoration(
labelText: 'Phone Number',
border: OutlineInputBorder(
borderSide: BorderSide(),
),
),
controller: _controller,
initialCountryCode: 'IN',
onChanged: (phone) {
debugPrint('Below is phone number');
debugPrint(phone.completeNumber);
debugPrint('Country code is: ${phone.countryCode}');
Country = phone.countryCode;
// phone.countryCode = _controller2 as String;
debugPrint(Country);
},
),
// Container(
// margin: const EdgeInsets.only(top: 40, right: 10, left: 10),
// child: TextField(
// decoration: const InputDecoration(
// hintText: 'Phone Number',
// prefix: Padding(
// padding: EdgeInsets.all(4),
// child: Text('+91'),
// ),
// ),
// maxLength: 10,
// keyboardType: TextInputType.number,
// controller: _controller,
// ),
// )
]),
Container(
margin: const EdgeInsets.all(10),
width: double.infinity,
child: FlatButton(
color: Colors.blue,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
OTPScreen(_controller.text, Country)));
},
child: const Text(
'Next',
style: TextStyle(color: Colors.white),
),
),
)
],
),
);
}
}
otp.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
import 'package:pinput/pinput.dart';
class OTPScreen extends StatefulWidget {
final String phone;
final String countryCode;
const OTPScreen(this.phone, this.countryCode, {Key? key}) : super(key: key);
#override
_OTPScreenState createState() => _OTPScreenState();
}
class _OTPScreenState extends State<OTPScreen> {
final GlobalKey<ScaffoldState> _scaffoldkey = GlobalKey<ScaffoldState>();
late String _verificationCode;
final TextEditingController _pinPutController = TextEditingController();
final FocusNode _pinPutFocusNode = FocusNode();
final BoxDecoration pinPutDecoration = BoxDecoration(
color: const Color.fromRGBO(43, 46, 66, 1),
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
color: const Color.fromRGBO(126, 203, 224, 1),
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldkey,
appBar: AppBar(
title: const Text('OTP Verification'),
),
body: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 40),
child: Center(
child: Text(
'Verify ${widget.countryCode} ${widget.phone}',
style:
const TextStyle(fontWeight: FontWeight.bold, fontSize: 26),
),
),
),
Padding(
padding: const EdgeInsets.all(30.0),
child: Pinput(
length: 6,
// fieldsCount: 6,
// textStyle: const TextStyle(fontSize: 25.0, color: Colors.white),
// eachFieldWidth: 40.0,
// eachFieldHeight: 55.0,
// focusNode: _pinPutFocusNode,
// controller: _pinPutController,
// submittedFieldDecoration: pinPutDecoration,
// selectedFieldDecoration: pinPutDecoration,
// followingFieldDecoration: pinPutDecoration,
// pinAnimationType: PinAnimationType.fade,
onSubmitted: (pin) async {
debugPrint('submit pressed');
try {
await FirebaseAuth.instance
.signInWithCredential(PhoneAuthProvider.credential(
verificationId: _verificationCode, smsCode: pin))
.then((value) async {
if (value.user != null) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Home()),
(route) => false);
}
});
} catch (e) {
FocusScope.of(context).unfocus();
_scaffoldkey.currentState!.showSnackBar(
const SnackBar(content: Text('invalid OTP')));
}
},
),
)
],
),
);
}
_verifyPhone() async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: '${widget.countryCode}${widget.phone}',
verificationCompleted: (PhoneAuthCredential credential) async {
await FirebaseAuth.instance
.signInWithCredential(credential)
.then((value) async {
if (value.user != null) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Home()),
(route) => false);
}
});
},
verificationFailed: (FirebaseAuthException e) {
debugPrint(e.message);
},
codeSent: (String verficationID, int? resendToken) {
setState(() {
_verificationCode = verficationID;
});
},
codeAutoRetrievalTimeout: (String verificationID) {
setState(() {
_verificationCode = verificationID;
});
},
timeout: const Duration(seconds: 120));
}
#override
void initState() {
// TODO: implement initState
super.initState();
_verifyPhone();
}
}
home.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'login.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
late String uid;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
IconButton(
icon: const Icon(Icons.logout),
onPressed: () async {
await FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const LoginScreen()),
(route) => false);
},
)
],
),
body: Center(
child: Text(uid),
),
);
}
#override
void initState() {
// TODO: implement initState
super.initState();
uid = FirebaseAuth.instance.currentUser!.uid;
}
}
One perfect way is to store the data in shared preferences. All you need in to add the flutter shared_preference package [https://pub.dev/packages/shared_preferences].
CONFIGURATION
After adding this package, create a shared_preference object like: * final preference = await SharedPreference.getInstance*
Next you can store the logs on the mobile storage using the preference object. For example, to store a variable isAuthenticated(which stores the authentication as bool) status of the user, do something like: * await preference.setBool("authentication", isAuthenticated)*
Step three, create another method to retrieve the data from storage.
first create another preference object loke in step one(1). But this time instead of setBool, use getBool like:* final isAlreadyAuthenticated = preferences.getBool("authentication")*
Now isAleadyAuthenticated holds the value whether is user already login or not and can you can use it to display a login screen of the value is false
Since you are using firebase, i recommed you add the firebase_auth package. And then you wrap the MyApp with a stream builder and supply FirebaseAuth.instance.authStateChanges as stream to the stream parameter which comes with the firebase_auth
So in the builder of the stream builder, return the MyApp() if snapshot.hasData, else return the OTP screen

Login with Facebook not working as expected - flutter

I'm trying to implement login with Facebook in my app which it's "working" but not necessarily as expected, I'll write down the issues I'm having.
When I try to login, I don't get redirected to the homepage and the logs show an error this error:
W/Firestore(27484): (24.1.2) [Firestore]: Listen for Query(target=Query(users where Email==random_email#gmail.com order by name);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
E/flutter (27484): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
I'm redirected to the login page again and the login only works in the second try.
When I sign out it looks like it works fine because I got redirected to the login page but the logs show the same error above.
For last some times it happens that if I exit the app(by pressing back button) and then re-open I get redirected to the home page instead of the login page it doesn't happen always so not sure what is causing that. I'm displaying the user data in the home page and in this case it's empty.
I was thinking that it could be related to my rules set in firebase but I'm not really sure , I would appreciate it very much if someone could guide me or point me what I'm missing or doing incorrectly.
Below my code:
main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Wrapper(),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => const HomePage(),
'/login': (BuildContext context) => const LoginPage(),
},
);
}
}
wrapper.dart
class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
//print(FirebaseAuth.instance.currentUser);
if(FirebaseAuth.instance.currentUser?.email == null){
return const LoginPage();
}
else{
return const HomePage();
}
}
}
login_page.dart
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
String get title => 'login';
#override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
String userEmail = "";
UserModel? _currentUser;
bool loading = false;
#override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 10.0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Email',
),
),
),
const Padding(
padding:
EdgeInsets.symmetric(horizontal: 8.0, vertical: 10.0),
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Password',
),
)),
CustomWidgets.socialButtonRect('Login with Facebook',
facebookColor, FontAwesomeIcons.facebookF, onTap: () async {
await signInWithFacebook();
}),
Padding(
padding: const EdgeInsets.all(15.0),
child:
loading ? const CircularProgressIndicator() : Container(),
),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
),
onWillPop: () async {
final shouldPop = await showDialog<bool>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Do you want to go exit?'),
actionsAlignment: MainAxisAlignment.spaceBetween,
actions: [
TextButton(
onPressed: () {
Navigator.pop(context, true);
},
child: const Text('Yes'),
),
TextButton(
onPressed: () {
Navigator.pop(context, false);
},
child: const Text('No'),
),
],
);
},
);
return shouldPop!;
},
);
}
Future<void> signInWithFacebook() async {
final LoginResult loginResult =
await FacebookAuth.instance.login(permissions: ['email']);
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken!.token);
final userData = await FacebookAuth.instance.getUserData();
FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
var snapshot = await FirebaseFirestore.instance
.collection('users')
.where('Email', isEqualTo: userData['email'])
.get();
if (snapshot.size == 0) {
await FirebaseFirestore.instance
.collection('users')
.add({'Email': userData["email"], 'Name': userData['name']});
}
//userEmail = userData["email"];
UserModel user = UserModel.fromJson(userData);
_currentUser = user;
setState(() {
loading = true;
});
Navigator.pushNamed(context, '/home');
}
}
home_page.dart
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FirebaseAuth auth = FirebaseAuth.instance;
bool loading = false;
String name = "";
#override
Widget build(BuildContext context) {
getName();
return Scaffold(
backgroundColor: Colors.blue,
bottomNavigationBar: const BottomBar(),
body: SafeArea(
child: Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 2,
itemBuilder: (context, index) {
return matchTile();
}),
Center(
child: ElevatedButton(
onPressed: () async {
//Navigator.pop(context,true);
//Navigator.popUntil(context, ModalRoute.withName('/login'));
Navigator.of(context).pushReplacementNamed('/login');
await signOut();
},
child: Text(name),
style: TextButton.styleFrom(
primary: Colors.redAccent,
onSurface: Colors.red,
),
),
),
],
),
),
);
}
Future<void> signOut() async {
await FacebookAuth.i.logOut();
await FirebaseAuth.instance.signOut();
}
Future<void> getName() async {
User? user = auth.currentUser;
await user?.reload();
user = auth.currentUser;
String? temp = user?.email;
var snapshot = await FirebaseFirestore.instance
.collection('users')
.where('Email', isEqualTo: temp)
.limit(1)
.get()
.then((value) => value.docs[0]);
Map<String, dynamic> data = snapshot.data();
//print('the lenght : $data.length');
setState(() {
name = data['Name'];
});
}
}
For last these are the rules I have set in firebase
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
You probably are missing an await.
Without this await the user is not logged when accessing Firestore, as the code "just runs by".
await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);

Flutter Firebase Authentication not moving to Dashboard page after authentication

I'm trying to authenticate user login with firebase, but I have a problem when it has to move to a dashboard page after successful login. The login is successful, but it's not doing anything after login.
Here's my code:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const FirsApp());
}
class FirsApp extends StatelessWidget {
const FirsApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<AuthenticationService>(
create: (context) => AuthenticationService(FirebaseAuth.instance)),
StreamProvider(
create: (_) =>
context.read<AuthenticationService>().authStateChanged,
initialData: const [])
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'First App',
theme: ThemeData(
primaryColor: appPrimaryColour,
scaffoldBackgroundColor: appBackGroupCoulour,
),
home: const AuthenticationWrapper(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
const AuthenticationWrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User?>();
if (firebaseUser != null) {
return const Dashboard();
}
return const SignInPage();
}
}
class SignInPage extends StatelessWidget {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TextField(
controller: emailController,
decoration: InputDecoration(
labelText: "Email",
),
),
TextField(
controller: passwordController,
decoration: InputDecoration(
labelText: "Password",
),
),
RaisedButton(
onPressed: () {
context.read<AuthenticationService>().signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
},
child: Text("Sign in"),
)
],
),
);
}
}
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
Stream<User?> get authStateChanged => _firebaseAuth.authStateChanges();
Future<String?> signInWithEmailAndPassword(
{required String email, required String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return "Singed in";
} on FirebaseAuthException catch (e) {
return e.message;
}
}
}
I did put a breakpoint on the AuthenticationService and it did return Singed in, but it never moved to the dashboard page. The dashboard page is just an empty page with a container and a text field.

Flutter Bloc is not emitting or triggering the event

I am building a mobile application using Flutter. I am using Bloc Flutter library. I am a beginner to Flutter BloC. Now, I am refactoring my login form using BLoC. But it seems that it is not dispatching the BLoC event when the login button is clicked.
I have the LoginBloc class with the following code:
class LoginBloc extends Bloc<LoginEvent, LoginState> {
LoginBloc() : super(LoginState.initial()) {
on<LoginEvent>((event, emit) {
// yield the state here. check the event and then process the event and yield the state based on the result.
if (event is Login) {
ApiService.post(ApiEndpoints.login, {
'email': event.email,
'password': event.password
}).then((response) => () {
if (response.statusCode == 200) {
// TODO: provide implementation
var responseJson = jsonDecode(response.body);
MeData meData = MeData.fromJson(responseJson['data']);
} else {
ApiError apiError = Utilities.parseApiError(response.body);
emit(LoginState(event.email, event.password, false, apiError));
}
}).onError((error, stackTrace) => () {
var apiError = ApiError();
apiError.setGenericErrorMessage("Something went wrong!");
emit(LoginState(event.email, event.password, false, apiError));
});
}
});
}
}
The is my login_event.dart file:
part of 'login_bloc.dart';
#immutable
abstract class LoginEvent extends Equatable {
const LoginEvent();
}
class Login extends LoginEvent {
final String email = "";
final String password = "";
const Login(email, password);
#override
List<Object?> get props => [
email,
password
];
}
This is my login_state.dart file:
part of 'login_bloc.dart';
class LoginState extends Equatable {
final String email;
final String password;
final bool isLoading;
final ApiError error;
const LoginState(this.email, this.password, this.isLoading, this.error);
static LoginState initial()
{
return LoginState("", "", false, ApiError());
}
#override
List<Object?> get props => [
email,
password,
isLoading,
error
];
}
This is my login.dart file (screen)
class LoginPage extends StatefulWidget {
final String title = 'Login';
#override
State<LoginPage> createState() => _LoginPage();
}
class _LoginPage extends State<LoginPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String? _email;
String? _password;
ApiError _apiError = ApiError();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title)
),
body: BlocBuilder<LoginBloc, LoginState>(
builder: (context, state) {
return Center(
child: Form(
key: _formKey,
child: Column(
children: [
GenericFormError(errorMessage: state.error.getGenericErrorMessage()),
Padding(
padding: const EdgeInsets.all(10),
child: TextFormField(
decoration: InputDecoration(
labelText: "Email",
border: const OutlineInputBorder(),
errorText: _apiError.getFieldError("email")
),
onChanged: (value) => setState(() {
_email = value;
}),
validator: (value) {
if (value == null || value.isEmpty) {
return "Please enter email";
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.all(10),
child: TextFormField(
obscureText: true,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: "Password",
border: const OutlineInputBorder(),
errorText: _apiError.getFieldError("password")
),
onChanged: (value) => setState(() {
_password = value;
}),
validator: (value) {
if (value == null || value.isEmpty) {
return "Please enter password";
}
return null;
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: () {
var isValid = _formKey.currentState!.validate();
if (isValid) {
context.read<LoginBloc>().add(Login(_email.toString(), _password.toString()));
}
},
child: const Text('Login'),
),
),
),
],
),
)
);
}
),
);
}
}
As you can see in the login form, when the button is clicked and form is valid, I am dispatching the BLoC event using this code.
context.read<LoginBloc>().add(Login(_email.toString(), _password.toString()));
But it is not triggering LoginBloc() at all. What is wrong with my code and how can I fix it? It is not throwing any errors either.
This is how I initialised the Bloc Provider:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (BuildContext context) {
return LoginBloc();
})
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Shar Kya Mal'),
));
}
}
I think you haven't initialized the bloc provider for it yet. You can wrap whole widget with bloc provider and init LoginBloc or init on file app
Adding Bloc Provider in file app.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
home: Scaffold(
body: BlocProvider(
create: (context) => NameBloc(NameBlocRepository()),
child: HomeScreen(),
),
));
}
}
or this
init bloc service and add to bloc provider
_nameBloc = nameBloc(blocService: _blocService);
return MultiBlocProvider(
providers: [ BlocProvider.value( value: _userBloc, )], child: MaterialApp

Unable to navigate to homepage after register with firebase Flutter

Im trying to navigate to homepage after login, this works, i followed this one tutorial:
https://www.youtube.com/watch?v=oJ5Vrya3wCQ&t=307s
But, my problem is when i go to register button > register an user and it takes me straight to the login page but when I fill in the login forms and log in, nothing happens, i must to do a "hot restart" to see my homepage, it is as if some widget did not rebuild. So i should do any better clean way to do this statemanagement?
Main:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:plantsapp/screens/login_page.dart';
import 'package:plantsapp/screens/plant_screen.dart';
import 'package:plantsapp/screens/register_page.dart';
import 'package:plantsapp/screens/shop_scree_page.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(create: (context) => context.read<AuthenticationService>().authStateChanges)
],
child: MaterialApp(
title: 'Flutter Plant Shop UI',
debugShowCheckedModeBanner: false,
home: AuthenticationWrapper(),
routes: {
'registerpage': (context) => RegisterPage(),
'loginpage': (context) => LoginPage(),
'homepage': (context) => PlantScreen(),
},
//theme: ThemeData.dark(),
),
);
}
}
// ignore: must_be_immutable
class AuthenticationWrapper extends StatelessWidget with ChangeNotifier{
#override
Widget build(BuildContext context) {
final firebaseuser = context.watch<User>();
notifyListeners();
if(firebaseuser != null) {
notifyListeners();
return ShopScreen();
} else {
notifyListeners();
return LoginPage();
}
}
}
Authentication service:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
class AuthenticationService with ChangeNotifier{
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
notifyListeners();
return "Signed in";
} on FirebaseAuthException catch (e) {
print(e);
return e.message;
}
}
Future<String> signUp({String email, String password, BuildContext context}) async{
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
print('USUARIO REGISTRADO');
Navigator.pushReplacementNamed(context, 'loginpage');
return "Signed Up";
} on FirebaseAuthException catch (e) {
print(e.message);
return e.message;
}
}
Future<void> signOut() async{
await _firebaseAuth.signOut();
notifyListeners();
}
}
LoginPage:
import 'package:flutter/material.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
class LoginPage extends StatefulWidget{
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage>{
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Login',
style: TextStyle(fontSize: 20),
),
_emailForm(),
_passwordForm(),
_button(),
_buttonRegister(),
],
),
),
),
);
}
Widget _emailForm() {
return TextField(
controller: emailController,
decoration: InputDecoration(hintText: ('Email')),
);
}
Widget _passwordForm() {
return TextField(
controller: passwordController,
decoration: InputDecoration(hintText: ('Password')),
);
}
Widget _button() {
return RaisedButton(
child: Text('Login'),
onPressed: () {
Provider.of<AuthenticationService>(context, listen: false).signIn(
email: emailController.text.trim(),
password: passwordController.text.trim());
},
);
}
_buttonRegister() {
return RaisedButton(
child: Text('Registrarse'),
onPressed: () {
Navigator.pushReplacementNamed(context, 'registerpage');
},
);
}
}
RegisterPage:
import 'package:flutter/material.dart';
import 'package:plantsapp/services/authentication_service.dart';
import 'package:provider/provider.dart';
class RegisterPage extends StatefulWidget {
RegisterPage({Key key}) : super(key: key);
#override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Registrarse',
style: TextStyle(fontSize: 30),
),
_emailForm(),
_passwordForm(),
_button(),
],
),
),
),
);
}
Widget _emailForm() {
return TextField(
controller: emailController,
decoration: InputDecoration(hintText: ('Email')),
);
}
Widget _passwordForm() {
return TextField(
controller: passwordController,
decoration: InputDecoration(hintText: ('Password')),
);
}
Widget _button() {
return RaisedButton(
child: Text('Registrarse'),
onPressed: () {
Provider.of<AuthenticationService>(context, listen: false).signUp(
email: emailController.text.trim(),
password: passwordController.text.trim(),
context: context);
},
);
}
}
Basically, I would say that using provider package in this simplest scenario is not really necessary. Handling authentication state with Firebase can be easily achieved with StreamBuilder and FirebaseAuth.instance.authStateChanges().
So instead of pushing pages with navigator and calling notifyListeners(), just make a streamBuilder which rebuilds whenever authentication state changes (firebase auth package handles simplest state management for you, providing you handy stream of User objects)
StreamBuilder<User>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.data == null) return LoginScreen();
return YourScreenForSignedUsersScreen();
})
i found the problem and i want to share it with all. The problem was the navigator, you have to maintain the flow, my app starts on the LoginPage so i use Navigator to go to RegisterPage, so, i start the app in the RegisterPage without using any Navigator between and test it, and its sends me to the HomePage automatically.