Flutter:在firebaseAuth错误上显示小吃栏



我有一个带有文本字段的屏幕,当按下按钮时,它们被发送给一个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));
}
}
}

相关认证功能:

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函数,我怎么能把这个错误,并把它变成一个零食栏/对话框显示在同一屏幕上的文本字段?它目前正在打印错误,但这对用户体验没有太大帮助。谢谢你!

我会在相应的状态下捕获SigninCubitemit中的错误。实际上,你已经在用emit(state.copyWith(status: SigninStatus.error));

然后您可以使用BlocListener<SigninCubit, SigninState>并侦听状态变化。当你的状态改变并且有statusSigninStatus.error时,你想要显示零食栏。

看起来像这样:

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()
...

您也可以使用BlocListenerBlocBuilder组合的BlocConsumer

这样做的一个缺点是,只要状态为SigninStatus.error,每次状态对象的任何更改都会再次显示小吃栏。

因此,您应该通过另一个变量(如snackbarDisplayed)跟踪显示-零食栏状态,该变量在显示后设置true,并在发出新错误时重置为false

或者你可以通过在你的状态中设置一个专用的可空error字段来consume错误,在显示零食栏后设置null

在我的最新项目中,我使用了后一种方法。为此,我的cubit有

方法
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();
}

相关内容

最新更新