颤振集团模式向后导航导致错误状态

时间:2018-10-24 05:29:49

标签: stream navigation flutter

我对带颤振的集团盘有疑问/问题。 目前,我正在这样启动我的应用程序

class _MyAppState extends State<MyApp> {

@override
  Widget build(BuildContext context) {        
    return BlocProvider(
        bloc: MyBloc(),
        child: MaterialApp(
          title: "MyApp",
          home: MyHomePage(),    
          routes: {
            '/homePage': (context) => MyHomePage(),
            '/otherPage': (context) => OtherPage(),
            '/otherPage2': (context) => OtherPage2(),
            ...
          },
        ));

这样我就可以像这样检索/访问myBloc

myBloc = BlocProvider.of(context) as MyBloc;

以及由状态表示的数据,例如

BlocBuilder<MyBlocEvent, MyObject>(
    bloc: myBloc,
    builder: (BuildContext context, MyObject myObject) {         
     ....
     var t = myObject.data;
     ....
     myBloc.onFirstEvent();
     ...
 }; 

我需要的地方。

MyBloc是这样实现的:

abstract clas MyBlocEvent {}
class FirstEvent extends MyBlocEvent {}
class SecondEvent extends MyBlocEvent {}

class MyBloc extends Bloc<MyBlocEvent , MyObject>

void onFirstEvent()
{
  dispatch(FirstEvent());
}

void onSecondEvent()
{
  dispatch(SecondEvent());
}

@override
Stream<MyObject> mapEventToState( MyObject state, MyBlocEvent event) async* {
if (event is FirstEvent) {
    state.data = "test1";
}
else if (event is SecondEvent) {
    state.otherData = 5;
}
    yield state;
}

我现在遇到的问题是,一旦我改变状态值并调用

Navigator.pop(context)

要返回当前堆栈,我无法更改状态,因为底层流似乎已关闭。失败并显示以下消息:

引发了另一个异常:错误状态:调用close之后无法添加新事件”

现在这只会在我打电话给pop之后发生。如果我只按新的屏幕,我可以愉快地更改状态数据,而不会出现任何问题。

我在这里的“导航”上做错什么了吗,还是在颤振或集团模式本身方面我没有发现其他问题?

2 个答案:

答案 0 :(得分:3)

  

状态错误:调用close后无法添加新事件

此错误表示您在调用purpose score elastic之后的add 上调用StreamController

close

这可能与您在 var controller = StreamController<int>(); controller.close(); controller.add(42); // Bad state: Cannot add new events after calling close 方法内将close称为“错误”窗口小部件有关。

一个好的经验法则是从不放置/关闭在创建它的小部件外部的对象。这样可以确保您不能使用已经处理过的对象。

答案 1 :(得分:2)

希望这有助于调试。

应用的导航取决于您的小部件设计。

我使用无状态小部件,并使用bloc的数据呈现视图。

每当我导航到另一个页面时,我都会弹出当前窗口小部件并导航到下一个窗口小部件。

下一个无状态小部件声明了整块, 然后在您的后续无状态小部件中应包含诸如MyBloc.dispatch(event(param1: value1, param2: value2));

之类的调用

在MyBloc中,您需要设置包含最终值的状态的工厂;

@override
Stream<MyObject> mapEventToState( MyObject state, MyBlocEvent event) async* {
if (event is FirstEvent) {
    // set it in the state, so this code is omitted
    // state.data = "test1";
    // add this
    yield state.sampleState([], "test1");
}
else if (event is SecondEvent) {
    // state.otherData = 5;
    yield state.sampleState([], 5);
} else {
    yield state.sampleState([], null);
}

需要这样设置MyObjectState,

class MyObjectState {
  final List<Bar> bars;
  final String Foo;

  const MyObjectState(
      {this.bars,
      this.foo,
  });

  factory MyObjectState.sampleState(List<Bar> barList, String value1) {
    return MyObjectState(bars: barList, foo: message);
  }
}

这样无状态小部件可以使用这样的bloc MyBloc.currentState.sampleState.foo

您可以尝试运行Felix Angelov的flutter项目。 Login Flow Example