Lit*_*key 12 state handle flutter bloc
在登录视图中,如果用户在没有插入凭据的情况下点击登录按钮,则 LoginFailState 为 yield 并且视图对其做出反应。如果他再次点击,这个 LoginFailstate 又是 yield ,但视图不会对它做出反应。那么,有没有办法在相同的状态下产生更多倍的结果?
有一些代码可以更好地解释我的情况:
class LoginBloc extends Bloc<LoginEvent, LoginState> {
@override
LoginState get initialState => LoginUninitialized();
@override
Stream<LoginState> mapEventToState(LoginEvent event) {
if (event is loginButtonPressed) {
yield LoginFailState();
}
}
Run Code Online (Sandbox Code Playgroud)
看法:
@override
Widget build(BuildContext context) {
return BlocBuilder(
bloc: _loginBloc,
builder: (BuildContext context, LoginState state) {
if (state is LoginFail) {
print ('Login fail');
}
return Column(
...
)
Run Code Online (Sandbox Code Playgroud)
zab*_*son 14
如果您不扩展 Equitable,或者实现您自己的“==”逻辑使两个 LoginFailStates 相等,您可以收到“相同”状态的更新。
解决方案是在两者之间产生一个不同的状态,就像在 Bloc 示例中一样。
yield LoginLoading();
Run Code Online (Sandbox Code Playgroud)
每次点击登录按钮时都会调用它。Felangel 的 LoginBloc 示例。
Ole*_*hyn 12
当您尝试发出与 Bloc 当前状态相等的新状态时,将不会发出新状态。
此行为是设计使然,将在此处进行讨论。
当我说“比较相等”时,我的意思是两个状态对象的 == 运算符返回 true。
有两种正确的方法:
identityHashCode(this)在这种情况下,只需将函数调用的结果添加到propsgetter 实现中即可:class NeverEqualState extends Equatable {
@override
List<Object?> get props => [identityHashCode(this)];
}
Run Code Online (Sandbox Code Playgroud)
请注意,identityHashCode无论运算符 == 是否重载,我都可以使用它。相比之下,hashCode这里就行不通了。
警告:
List<Object> get props => [Random().nextDouble()];。随机变量是随机的,这意味着您仍然可能以极低的概率在序列中获得两个相等的值,从而破坏此解决方法。这是极不可能的,因此不可能重现和调试它。get props实现中包含字段,但请记住,当所有字段比较相等时,对象也将比较相等。最后,为什么你想让一个状态类扩展 Equatable 但仍然不比较相等?当您的状态类实际上是层次结构的根时,可能需要这样做,其中一些后代需要正确实现 == 运算符,而另一些则需要永远不比较相等。这是示例:
class BaseMapState extends Equatable {
const BaseMapState();
@override
List<Object?> get props => [];
}
class MapState extends BaseMapState {
final Map<String, Report> reports;
final Report? selectedReport;
final LatLng? selectedPosition;
final bool isLoadingNewReports;
const MapState(
{this.reports = const {},
this.selectedReport,
this.selectedPosition,
this.isLoadingNewReports = false});
@override
List<Object?> get props => [
...reports.values,
selectedReport,
selectedPosition,
isLoadingNewReports
];
}
class ErrorMapState extends BaseMapState {
final String? error;
const ErrorMapState(this.error);
@override
List<Object?> get props => [identityHashCode(this), error];
}
class NeedsAuthMapState extends ErrorMapState {
const NeedsAuthMapState() : super('Authentication required');
}
class NoInternetMapState extends ErrorMapState {
const NoInternetMapState() : super("No Internet connection");
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,当相同的状态将一个接一个地传递时,BLoC 模式不会发出状态。一种方法是在传递LoginFailState.
因此,在用户单击带有错误凭据的按钮后,传递的状态不会是:
LoginFailState()
LoginFailState()
Run Code Online (Sandbox Code Playgroud)
但
LoginFailState()
LoginEmptyState()
LoginFailState()
LoginEmptyState()
Run Code Online (Sandbox Code Playgroud)
这将使 UI 对它们中的每一个做出反应。
但我认为最好和最干净的解决方案是在通过LoadingState之前从 BLoC 传递LoginFailState()。
您可以关注我最近撰写的有关此主题的博客文章。
如果您使用 Equitable 并尝试发出具有不同属性的同一 State 的两个相等实例,请确保覆盖propsarray。通过重写props数组,Equitable 将知道如何比较状态实例。
class TablesLoadedState extends Equatable {
final List<TableEntity> tablesList;
TablesLoadedState(this.tablesList);
@override
List<Object> get props => [tablesList];
}
Run Code Online (Sandbox Code Playgroud)
因此,当 bloc 发出两个具有不同值的相同状态实例时,这些状态实例将传递给 BlocListener,并且 UI 将根据新数据进行更新。
| 归档时间: |
|
| 查看次数: |
5090 次 |
| 最近记录: |