英文:
Flutter: BlocConsumer does not listen to the state passed by the block
问题
I have an authorization page. After the user clicks "Log in," authorization takes place, and the block returns the required state. But my BlocConsumer does not change it and leaves the initial state "Initial State."
app.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:resourse_app/features/auth/auth_screen.dart';
import 'package:resourse_app/theme/theme.dart';
import 'package:resourse_app/utils/router/router.dart';
import 'features/auth/bloc/auth_bloc.dart';
class MyApp extends StatelessWidget {
const MyApp({Key? key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(
create: (BuildContext context) => AuthBloc(),
),
],
child: MaterialApp(
theme: lightTheme,
home: const AuthScreen(),
routes: router,
),
);
}
}
bloc.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:resourse_app/repositories/models/users/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
part 'auth_event.dart';
part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc() : super(AuthInitialState()) {
FirebaseAuth auth = FirebaseAuth.instance;
on<AuthSignInEvent>((event, emit) async {
emit(AuthLoadingState());
try {
final user = event.user;
await auth.signInWithEmailAndPassword(
email: user.login, password: user.password);
emit(AuthSignInState());
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
emit(AuthFailureState(
failureException: 'No user found for that email.'));
} else if (e.code == 'wrong-password') {
emit(AuthFailureState(
failureException: 'Wrong password provided for that user.'));
}
} catch (error) {
emit(AuthFailureState(failureException: error));
}
print("Переданный $state");
});
on<AuthSignUpEvent>((event, emit) async {
emit(AuthLoadingState());
try {
final user = event.user;
final UserCredential userCredential =
await auth.createUserWithEmailAndPassword(
email: event.user.login, password: event.user.password);
await FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user!.uid)
.set({
'userId': userCredential.user!.uid,
'mail': user.login,
'username': user.username,
});
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
emit(AuthFailureState(
failureException: 'The password provided is too weak.'));
} else if (e.code == 'email-already-in-use') {
emit(AuthFailureState(
failureException: 'The account already exists for that email.'));
}
} catch (error) {
emit(AuthFailureState(failureException: error));
}
});
}
}
event.dart
part of 'auth_bloc.dart';
abstract class AuthEvent {}
class AuthSignInEvent extends AuthEvent {
final UserSignIn user;
AuthSignInEvent({required this.user});
}
class AuthSignUpEvent extends AuthEvent {
final UserSignUp user;
AuthSignUpEvent({required this.user});
}
state.dart
part of 'auth_bloc.dart';
abstract class AuthState {}
class AuthInitialState extends AuthState {}
class AuthSignInState extends AuthState {}
class AuthSignUpState extends AuthState {}
class AuthLoadingState extends AuthState {}
class AuthFailureState extends AuthState {
final Object failureException;
AuthFailureState({required this.failureException});
}
signInScreen.dart
import 'package:flutter/material.dart';
import 'package:resourse_app/features/auth/widgets/sign_up_screen/sign_up.dart';
import '../../../../../repositories/models/users/user.dart';
import '../../../bloc/auth_bloc.dart';
class SignInScreen extends StatefulWidget {
static const String id = 'sign_in_screen';
const SignInScreen({Key? key}) : super(key: key);
@override
State<SignInScreen> createState() => _SignInScreenState();
}
class _SignInScreenState extends State<SignInScreen> {
final _formKey = GlobalKey<FormState>();
late final FocusNode _passFocusNode;
final _authBloc = AuthBloc();
String? _email;
String? _pass;
@override
void initState() {
_passFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
_passFocusNode.dispose();
super.dispose();
}
void _submit(BuildContext context) {
FocusScope.of(context).unfocus();
if (!_formKey.currentState!.validate()) {
// Invalid
return;
}
_formKey.currentState!.save();
UserSignIn user = UserSignIn(login: _email!, password: _pass!);
_authBloc.add(AuthSignInEvent(user: user));
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context).textTheme;
double wh = MediaQuery.of(context).size.width;
double hh = MediaQuery.of(context).size.height;
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
body: SafeArea(
child: Center(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListView(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
children: [
Center(
child: Text(
'Resourse',
style: theme.titleMedium,
),
),
SizedBox(
height: 35,
),
//e-mail
SizedBox(
height: 40,
child: TextFormField(
style: theme.labelSmall,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.grey, width: 1.0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.white, width: 1.0),
),
labelText: "Телефон или e-mail",
),
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_passFocusNode);
},
onSaved: (value) {
_email = value;
},
validator: (value) {
if (value!.isEmpty) {
return 'Укажите телефон или e-mail';
}
return null;
},
),
),
SizedBox(
height: 15,
),
//password
SizedBox(
height: 40,
child: TextFormField(
focusNode: _passFocusNode,
style: theme.labelSmall,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.grey, width: 1.0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
<details>
<summary>英文:</summary>
I have an authorization page. After the user clicks "Log in", authorization takes place and the block returns the required state. But my BlocConsumer does not change it and leaves the initial state "Initial State". Below is a part of the code of my project. I will be grateful for your help!
**app.dart**
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:resourse_app/features/auth/auth_screen.dart';
import 'package:resourse_app/theme/theme.dart';
import 'package:resourse_app/utils/router/router.dart';
import 'features/auth/bloc/auth_bloc.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider (
create: (BuildContext context) => AuthBloc(),
),
],
child: MaterialApp(
theme: lightTheme,
home: const AuthScreen(),
routes: router,
),
);
}
}
**bloc.dart**
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:resourse_app/repositories/models/users/user.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
part 'auth_event.dart';
part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
AuthBloc() : super(AuthInitialState()) {
FirebaseAuth auth = FirebaseAuth.instance;
on<AuthSignInEvent>((event, emit) async {
emit(AuthLoadingState());
try {
final user = event.user;
await auth.signInWithEmailAndPassword(
email: user.login, password: user.password);
emit(AuthSignInState());
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
emit(AuthFailureState(
failureException: 'No user found for that email.'));
} else if (e.code == 'wrong-password') {
emit(AuthFailureState(
failureException: 'Wrong password provided for that user.'));
}
} catch (error) {
emit(AuthFailureState(failureException: error));
}
print("Переданный $state");
});
on<AuthSignUpEvent>((event, emit) async {
emit(AuthLoadingState());
try {
final user = event.user;
final UserCredential userCredential =
await auth.createUserWithEmailAndPassword(
email: event.user.login, password: event.user.password);
await FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user!.uid)
.set({
'userId': userCredential.user!.uid,
'mail' : user.login,
'username' : user.username,
});
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
emit(AuthFailureState(
failureException: 'The password provided is too weak.'));
} else if (e.code == 'email-already-in-use') {
emit(AuthFailureState(
failureException: 'The account already exists for that email.'));
}
} catch (error) {
emit(AuthFailureState(failureException: error));
}
});
}
}
**event.dart**
part of 'auth_bloc.dart';
abstract class AuthEvent {}
class AuthSignInEvent extends AuthEvent {
final UserSignIn user;
AuthSignInEvent({required this.user});
}
class AuthSignUpEvent extends AuthEvent {
final UserSignUp user;
AuthSignUpEvent({required this.user});
}
**state.dart**
part of 'auth_bloc.dart';
abstract class AuthState {}
class AuthInitialState extends AuthState {}
class AuthSignInState extends AuthState {}
class AuthSignUpState extends AuthState {}
class AuthLoadingState extends AuthState {}
class AuthFailureState extends AuthState {
final Object failureException;
AuthFailureState({required this.failureException});
}
**signInScreen.dart**
import 'package:flutter/material.dart';
import 'package:resourse_app/features/auth/widgets/sign_up_screen/sign_up.dart';
import '../../../../../repositories/models/users/user.dart';
import '../../../bloc/auth_bloc.dart';
class SignInScreen extends StatefulWidget {
static const String id = 'sign_in_screen';
const SignInScreen({Key? key}) : super(key: key);
@override
State<SignInScreen> createState() => _SignInScreenState();
}
class _SignInScreenState extends State<SignInScreen> {
final _formKey = GlobalKey<FormState>();
late final FocusNode _passFocusNode;
final _authBloc = AuthBloc();
String? _email;
String? _pass;
@override
void initState() {
_passFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
_passFocusNode.dispose();
super.dispose();
}
void _submit(BuildContext context) {
FocusScope.of(context).unfocus();
if(!_formKey.currentState!.validate()) {
//Invalid
return;
}
_formKey.currentState!.save();
UserSignIn user = UserSignIn(login: _email!, password: _pass!);
_authBloc.add(AuthSignInEvent( user: user,));
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context).textTheme;
double wh = MediaQuery.of(context).size.width;
double hh = MediaQuery.of(context).size.height;
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
body: SafeArea(
child: Center(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListView(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
children: [
Center(
child: Text(
'Resourse',
style: theme.titleMedium,
),
),
SizedBox(
height: 35,
),
//e-mail
SizedBox(
height: 40,
child: TextFormField(
style: theme.labelSmall,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.grey, width: 1.0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.white, width: 1.0),
),
labelText: "Телефон или e-mail",
),
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_passFocusNode);
},
onSaved: (value) {
_email = value;
},
validator: (value) {
if (value!.isEmpty) {
return 'Укажите телефон или e-mail';
}
return null;
},
),
),
SizedBox(
height: 15,
),
//password
SizedBox(
height: 40,
child: TextFormField(
focusNode: _passFocusNode,
style: theme.labelSmall,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.grey, width: 1.0),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.white, width: 1.0),
),
labelText: "Пароль",
),
obscureText: true,
onFieldSubmitted: (_) {
//TODO:- submit
},
onSaved: (value) {
_pass = value;
},
validator: (value) {
if (value!.isEmpty) {
return 'Введите пароль';
}
return null;
},
),
),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
child: Text(
'забыли пароль?',
style: theme.labelSmall,
),
),
),
//Вход
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Вход
SizedBox(
width: wh * 0.3,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.white),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
onPressed: () {
_submit(context);
},
child: Text(
'Войти',
style: theme.labelMedium,
),
),
),
SizedBox(width: 20,),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.transparent),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
side: MaterialStateProperty.all(
const BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
onPressed: () {},
child: const Text(
'Войти с помощью google',
style: TextStyle(
fontFamily: "Ysabeau",
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.w400
),
),
),
],
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.center,
child: Text(
'или',
style: theme.labelSmall,
),
),
SizedBox(
height: 15,
),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.transparent),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
side: MaterialStateProperty.all(
const BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
onPressed: () {
Navigator.of(context).pushNamed(SignUpScreen.id);
},
child: const Text(
'Зарегистрироваться',
style: TextStyle(
fontFamily: "Ysabeau",
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.w400
),
),
),
],
),
),
),
),
),
),
);
}
}
**auth.dart**
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:resourse_app/features/home_page/view/home_page.dart';
import '../bloc/auth_bloc.dart';
import '../widgets/sign_in_screen/sign_in.dart';
class AuthScreen extends StatelessWidget {
const AuthScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
print(state);
if (state is AuthSignInState || state is AuthSignUpEvent) {
Navigator.of(context).popAndPushNamed(HomePage.id);
}
},
builder: (context, state) {
print("Переданный в widget $state");
if (state is AuthLoadingState) {
return const Center(
child: CircularProgressIndicator(
color: Colors.white,
),
);
}
if (state is AuthFailureState) {
return AlertDialog(
title: Text(state.failureException.toString()),
);
}
return const SignInScreen();
}
),
);
}
}
</details>
# 答案1
**得分**: 0
Sure, here is the translated code:
```dart
late final _authBloc;
@override
void initState() {
_authBloc = context.read();
//or _authBloc=context.read<AuthBloc>();
_passFocusNode = FocusNode();
super.initState();
}
英文:
final _authBloc = AuthBloc();
String? _email;
String? _pass;
@override
void initState() {
_passFocusNode = FocusNode();
super.initState();
}
change to
late final _authBloc;
@override
void initState() {
_authBloc = context.read();
//or _authBloc=context.read<AuthBloc>();
_passFocusNode = FocusNode();
super.initState();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论