【发布时间】:2020-09-03 04:56:05
【问题描述】:
我正在学习 bloc 并使用 equatable。
这是我的代码
login_state.dart
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
abstract class LoginState extends Equatable {
@override
List<Object> get props => [];
}
class LoginInitial extends LoginState {}
class LoginLoading extends LoginState {}
class LoginSuccess extends LoginState {
final Map token;
LoginSuccess({@required this.token});
}
class LoginFailure extends LoginState {
final Map error;
LoginFailure({@required this.error});
@override
List<Object> get props => null;
}
login_view
@override
Widget build(BuildContext context) {
final bool loading = _authStore.loading;
return BlocProvider(
create: (BuildContext context) => _loginBloc,
child: BlocListener<LoginBloc, LoginState>(
listener: (BuildContext context, state) {
if (state is LoginFailure) {
print("loginFailure is triggered with ${state.error}");
FlashAlert(context: context, message: state.error['message']).showFlash();
}
},
child: Scaffold(
resizeToAvoidBottomInset: true,
resizeToAvoidBottomPadding: true,
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: spacing(3)),
margin: EdgeInsets.only(top: spacing(2)),
child: widget.isLogin ? loginView() : registerView(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: theme.primaryColor,
onPressed: () {
widget.isLogin ? handleLogin('') : handleRegister();
},
child: loading ? Progress() : Icon(EvaIcons.arrowIosForward),
),
),
));
}
我尝试将 [error] 放在 get props 上。
@override
List<Object> get props => [error];
问题是FlashAlert 仅在发生错误时运行 1 次。如何继续使用 equatable 但在发生错误时继续触发FlashAlert?。
谢谢。
----- 使用 blocbuilder 编辑 ---
@override
Widget build(BuildContext context) {
final bool loading = _authStore.loading;
return BlocProvider(
create: (BuildContext context) => _loginBloc,
child: BlocBuilder<LoginBloc, LoginState>(builder: (BuildContext context, state) {
if (state is LoginFailure) {
print("loginFailure is triggered with ${state.error}");
FlashAlert(context: context, message: state.error['message']).showFlash();
}
return Scaffold(
resizeToAvoidBottomInset: true,
resizeToAvoidBottomPadding: true,
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: spacing(3)),
margin: EdgeInsets.only(top: spacing(2)),
child: widget.isLogin ? loginView() : registerView(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: theme.primaryColor,
onPressed: () {
widget.isLogin ? handleLogin('') : handleRegister();
},
child: state is LoginLoading ? Progress() : Icon(EvaIcons.arrowIosForward),
),
);
}),
);
}
返回错误:
VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: setState() or markNeedsBuild() called during build.
This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
Overlay-[LabeledGlobalKey<OverlayState>#21a25]
【问题讨论】:
-
显示您的 LoginBloc 文件
-
一个快速的解决方法是 yield
LoginLoading,然后LoginFailure强制更新,或添加特殊状态LoginFailureBuffing以保持逻辑。