Flutter:在firebaseAuth错误上显示snackbar

avwztpqn  于 2023-10-22  发布在  Flutter
关注(0)|答案(2)|浏览(145)

我有一个带有文本字段的屏幕,当按下按钮时,它们被发送到一个cubit用于登录功能。我想做的是,当一个认证错误发生时,我想创建一个相关的小吃栏或对话框,但我有麻烦实现它。
文本字段:

CustomLoginTextField(
                      controller: emailController,
                      hint: 'ENTER YOUR EMAIL',
                      onChanged: (value) {
                        context.read<SigninCubit>().emailChanged(value);

                        //print(context.read<SigninCubit>().state.email);
                      },
                    ),
                    CustomLoginTextField(
                      controller: passwordController,
                      hint: 'ENTER YOUR PASSWORD',
                      onChanged: (value) {
                        context.read<SigninCubit>().passwordChanged(value);
                        //print(context.read<SigninCubit>().state.password);
                        // print(passwordController.text);
                      },
                    ),

相关按钮代码:

if (tabController.index == 3) {
            context.read<SigninCubit>().signInWithCredentials();
          }

腕尺状态:

part of 'signin_cubit.dart';

enum SigninStatus { initial, submitting, success, error }

class SigninState extends Equatable {
  final String email;
  final String password;
  final SigninStatus status;

  bool get isFormValid => email.isNotEmpty && password.isNotEmpty;

  const SigninState({
    required this.email,
    required this.password,
    required this.status,
  });

  factory SigninState.initial() {
    return SigninState(
      email: '',
      password: '',
      status: SigninStatus.initial,
    );
  }

  @override
  bool get stringify => true;

  @override
  List<Object> get props => [email, password, status];

  SigninState copyWith({
    String? email,
    String? password,
    SigninStatus? status,
  }) {
    return SigninState(
      email: email ?? this.email,
      password: password ?? this.password,
      status: status ?? this.status,
    );
  }
}

腕尺:

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:hero/repository/auth_repository.dart';

part 'signin_state.dart';

class SigninCubit extends Cubit<SigninState> {
  final AuthRepository _authRepository;

  SigninCubit({required AuthRepository authRepository})
      : _authRepository = authRepository,
        super(SigninState.initial());

  void emailChanged(String value) {
    emit(state.copyWith(email: value, status: SigninStatus.initial));
  }

  void passwordChanged(String value) {
    emit(state.copyWith(password: value, status: SigninStatus.initial));
  }

  void signInWithCredentials() async {
    try {
      await _authRepository.signInWithEmailAndPassword(
          email: state.email, password: state.password);
      emit(
        state.copyWith(status: SigninStatus.success),
      );
    } catch (e) {
      emit(state.copyWith(status: SigninStatus.error));
    }
  }
}

相关auth函数:

Future<User?> signInWithEmailAndPassword(
      {required String email, required String password}) async {
    try {
      final credential = await _firebaseAuth.signInWithEmailAndPassword(
          email: email, password: password);
      final user = _userFromFirebaseUser(credential.user);
      return user;
    } catch (e) {
      print(e);
    }
  }

在auth函数中,我如何将该错误转化为与文本字段显示在同一屏幕上的snackbar/对话框?它目前正在打印错误,但这对用户体验没有太大帮助。谢谢你,谢谢!

bgibtngc

bgibtngc1#

我会在你的SigninCubitemit对应的状态中捕获错误。实际上,您已经在使用emit(state.copyWith(status: SigninStatus.error));执行此操作
然后,您可以使用BlocListener<SigninCubit, SigninState>并侦听状态更改。每当你的状态发生变化,并且有一个statusSigninStatus.error,你就想显示这个snackbar。
它看起来像这样:

BlocListener<SigninCubit, SigninState>(
  listener: (context, state) {
    print('signinstate has changed');
    if(state.status == SigninStatus.error) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Oops... Something went wrong')),
      );
    }
  },
  child: YourWidgetTree()
  ...

您也可以使用BlocConsumer,它结合了BlocListenerBlocBuilder
这样做的一个缺点是,只要状态是SigninStatus.error,每当状态对象发生任何变化时,都会再次显示snackbar。
因此,您应该通过另一个变量(如snackbarDisplayed)来跟踪显示-snackbar-status,在显示后设置true,并在发出新错误时重置为false
或者你可以通过在你的状态中设置一个专用的可空的error字段来consume错误,在显示snackbar后设置null
在我最近的项目中,我使用了后一种方法。为此我的腕尺有方法

void clearError() => emit(state.copyWith(error: null));

我在这里使用这个方法:

void _consumeError(BuildContext context, String message) {
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('Oops... Something went wrong')),
  );
  context.read<MyCubit>().clearError();
}
qxgroojn

qxgroojn2#

on FirebaseAuthException catch (e) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Text(e.code),
      backgroundColor: Colors.red,
    ),
  );
  throw Exception(e.code);
}

}
在try块之后使用此代码,您需要Flutter中的Firebase身份验证包

相关问题