Flutter: BlocConsumer 不监听由 block 传递的状态

huangapple go评论62阅读模式
英文:

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 &quot;Log in&quot;, authorization takes place and the block returns the required state. But my BlocConsumer does not change it and leaves the initial state &quot;Initial State&quot;. 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(&#39;users&#39;)
.doc(userCredential.user!.uid)
.set({
&#39;userId&#39;: userCredential.user!.uid,
&#39;mail&#39; : user.login,
&#39;username&#39; : user.username,
});
} on FirebaseAuthException catch (e) {
if (e.code == &#39;weak-password&#39;) {
emit(AuthFailureState(
failureException: &#39;The password provided is too weak.&#39;));
} else if (e.code == &#39;email-already-in-use&#39;) {
emit(AuthFailureState(
failureException: &#39;The account already exists for that email.&#39;));
}
} 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(
&#39;Resourse&#39;,
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: &quot;Телефон или e-mail&quot;,
),
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_passFocusNode);
},
onSaved: (value) {
_email = value;
},
validator: (value) {
if (value!.isEmpty) {
return &#39;Укажите телефон или e-mail&#39;;
}
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: &quot;Пароль&quot;,
),
obscureText: true,
onFieldSubmitted: (_) {
//TODO:- submit
},
onSaved: (value) {
_pass = value;
},
validator: (value) {
if (value!.isEmpty) {
return &#39;Введите пароль&#39;;
}
return null;
},
),
),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
child: Text(
&#39;забыли пароль?&#39;,
style: theme.labelSmall,
),
),
),
//Вход
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Вход
SizedBox(
width: wh * 0.3,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all&lt;Color&gt;(
Colors.white),
shape:
MaterialStateProperty.all&lt;RoundedRectangleBorder&gt;(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
onPressed: () {
_submit(context);
},
child: Text(
&#39;Войти&#39;,
style: theme.labelMedium,
),
),
),
SizedBox(width: 20,),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all&lt;Color&gt;(Colors.transparent),
shape:
MaterialStateProperty.all&lt;RoundedRectangleBorder&gt;(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
side: MaterialStateProperty.all(
const BorderSide(
color: Colors.grey,
width: 1.0,
),
),
),
onPressed: () {},
child: const Text(
&#39;Войти с помощью google&#39;,
style:  TextStyle(
fontFamily: &quot;Ysabeau&quot;,
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.w400
),
),
),
],
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.center,
child: Text(
&#39;или&#39;,
style: theme.labelSmall,
),
),
SizedBox(
height: 15,
),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all&lt;Color&gt;(Colors.transparent),
shape:
MaterialStateProperty.all&lt;RoundedRectangleBorder&gt;(
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(
&#39;Зарегистрироваться&#39;,
style:  TextStyle(
fontFamily: &quot;Ysabeau&quot;,
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&lt;AuthBloc&gt;();
_passFocusNode = FocusNode();
super.initState();
}

huangapple
  • 本文由 发表于 2023年5月22日 17:29:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定