【问题标题】:Multiple yield calls overwrites previous state多个 yield 调用会覆盖先前的状态
【发布时间】:2021-09-12 13:54:29
【问题描述】:

我在我的应用程序中使用 Flutter Bloc 进行状态管理。

当使用 .copyWith() 模式连续产生多个新状态时, 未包含在最新 .copyWith() 调用中的状态成员设置为 null。

这种行为是有意的,还是我的颤振和/或 Bloc 版本太旧了? 我正在使用 Flutter 1.22.6 和 Flutter_bloc 6.1.3

//my_bloc_state.dart
class MyState extends Equatable {
  final String foo;
  final String bar;

  const MyState({this.foo, this.bar});


  MyState copyWith({
    String foo,
    String bar,
  }) {
    if ((foo == null || identical(foo, this.foo)) &&
        (bar == null || identical(bar, this.bar))) {
      return this;
    }

    return MyState(
      foo: foo ?? this.foo,
      bar: bar ?? this.bar
    );
  }

  @override
  List<Object> get props => [foo, bar];
}



//my_bloc.dart

@override
Stream<MyState> mapEventToState(MyEvent event) async* {
  if (event is MySpecialEvent) {
    yield state.copyWith(foo: "hello");

    yield state.copyWith(bar: "World");

    print(state.foo) // null
  }
}

【问题讨论】:

    标签: flutter bloc flutter-bloc


    【解决方案1】:

    我建议在任何情况下都更新您的库,将来其他依赖项会更容易。 我推荐的另一件事是使用Cubit 方法,您的代码已经看起来比原来的BLoC (https://pub.dev/packages/flutter_bloc) 更像它。 使用BLoC 时,建议为每个可能的状态变化设置一个事件。

    但是让我们在这里看看你的问题。 这个sn-p:

    return MyState(
      foo: foo ?? this.foo,
      bar: bar ?? this.bar
    );
    

    意味着MyState 将更新foobar 仅当它们不为空时,如果为空,它将返回之前的任何内容。 对我来说不好看的是您的 state 对象尚未更新为 yield 但您正在尝试打印它:

    print(state.foo) // null
    

    如果你真的想看看你的状态对象在yield 之后的样子,试着在之前添加这样的东西:

    state = state.copyWith(foo: "hello");
    print(state.foo);
    print(state.bar);
    
    state = state.copyWith(bar: "World");
    print(state.foo);
    print(state.bar);
    
    yield state;
    

    【讨论】:

    • 您好,感谢您的意见!一旦我更新到空安全,我一定会更新库。打印调用意味着在组件树中某处的 BlocBuilder 内。然而,我的问题措辞不当。每次调用由事件触发的 mapEventToState() 是否只能产生一个状态?
    【解决方案2】:

    认为这是问题

       @override
    Stream<MyState> mapEventToState(MyEvent event) async* {
      if (event is MySpecialEvent) {
        yield state.copyWith(foo: "hello");
    
        yield state.copyWith(bar: "World");
    
        print(state.foo) // null
      }
    }
    

    当您在此之后打印 foo 时

    yield state.copyWith(bar: "World");
    

    foo 值为 null,因为您没有在此处为其设置任何值。

    yield state.copyWith(foo: "hello");
    

    在这个状态之后 foo 的值为 "hello" 并且 bar 的值默认为 null。

    yield state.copyWith(bar: "World");
    

    在此状态覆盖之前的状态值后,bar 值默认为“world”,foo 值默认为 null。

    如果您需要同时获取最后一个状态,请按如下方式获取最终状态。

    替换最后一条收益线

    yield state.copyWith(bar: "World",foo: "hello");
    
    or 
    yield state.copyWith(bar: "World",foo: state.foo);
    

    两者都可以

    【讨论】:

      猜你喜欢
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      • 2018-09-29
      • 2019-06-15
      • 2021-09-05
      • 2021-06-10
      • 1970-01-01
      • 2019-08-28
      相关资源
      最近更新 更多