【问题标题】:Flutter Bloc - Button did not trigger state changeFlutter Bloc - 按钮未触发状态更改
【发布时间】:2020-05-14 17:48:40
【问题描述】:

我有一个main.dart 有自己的main_bloc.dartmain_event.dartmain_state.dart

main_event:
- AppStarted
- GoingHome
- GoingTestHome

main_State:
- StateHome
- StateTestHome

main_bloc:
Stream<MainState> mapEventToState(
    MainEvent event,
  ) async* {
    if (event is AppStarted) {
      print('mainbloc: AppStarted');
dispatch(GoingHome());
    }
    if (event is GoingHome) {
      print('mainbloc: GoingHome');
      yield StateHome();
    }
    if (event is TestHome) {
      print('mainbloc: TestHome');
      yield StateTestHome();
    }
...
}

在我的main.dart:

class _AppState extends State<App> {
  MainBloc _mainBloc;
  @override
  void initState() {
    super.initState();
    _mainBloc = MainBloc();
    _mainBloc.dispatch(AppStarted());/// <-- 1
  }
...

@override
  Widget build(BuildContext context) {
    return BlocProvider(
        builder: (_) => _mainBloc,
        child: MaterialApp(
          title: 'Home',
          theme: ThemeData(
            ...
          ),
          home: BlocListener<MainBloc, MainState>(
              bloc: _mainBloc,
              listener: (context, state) {
                print('state changed: ${state.toString()}');
                if (state is StateHome) {  /// <-- 2
                  print('main: StateHome');
                  _mainBloc.dispatch(TestHome()); /// <-- 2.1
                } else if (state is StateTestHome) {  /// <-- 3
                  print('main: StateTestHome');
                }
              },
              child: SplashPage()),
...

我做一个快速测试:

  1. 应用启动时,调用_mainBloc.dispatch(AppStarted()),会从main_bloc调用dispatch(GoingHome())
  2. BlocListener检测到状态变化('StateHome'),所以:

    print('main: StateHome'); _mainBloc.dispatch(TestHome());

  3. BlocListener再次检测到状态变化('StateTestHome'),所以:

    print('main: StateTestHome');

在控制台中,我可以依次看到所有的打印信息:

Restarted application in 1,612ms.
I/flutter (15369): mainbloc: AppStarted
I/flutter (15369): mainbloc: GoingHome
I/flutter (15369): state changed: StateHome
I/flutter (15369): main: StateHome
I/flutter (15369): mainbloc: TestHome
I/flutter (15369): state changed: StateTestHome
I/flutter (15369): main: StateTestHome

到目前为止,它按我预期的方式运行。

但是当我取出代码2.1,然后添加一个按钮来触发事件:

...
floatingActionButton: FloatingActionButton(
        child: Text('test'),
        onPressed: () {
          _mainBloc.dispatch(TestHome());
        },
      ),
...

我会得到这样的控制台:

Restarted application in 2,738ms.
I/flutter (15369): mainbloc: AppStarted
I/flutter (15369): mainbloc: GoingHome
I/flutter (15369): state changed: StateHome
I/flutter (15369): main: StateHome
I/flutter (15369):
I/flutter (15369): mainbloc: TestHome ///<-- button trigger

我希望:

Restarted application in 2,738ms.
I/flutter (15369): mainbloc: AppStarted
I/flutter (15369): mainbloc: GoingHome
I/flutter (15369): state changed: StateHome
I/flutter (15369): main: StateHome
I/flutter (15369):
I/flutter (15369): mainbloc: TestHome ///<-- button trigger
I/flutter (15369): state changed: StateTestHome ///<-- expectation
I/flutter (15369): main: StateTestHome          ///<-- expectation

似乎按钮交互没有yield 状态,或者BlocListener 没有捕获状态更改事件。

我在这里缺少什么?我该如何解决这个问题?

【问题讨论】:

  • 据我所知init()build() 之前触发,因此您在小部件树完全构建之前调度您的事件。试试这个:builder: (_) =&gt; _mainBloc.dispatch(AppStarted()),在build() func
  • 你知道BlocDelegate吗?你可以用它来观察statesevents,你可以释放一些print:P

标签: flutter dart bloc


【解决方案1】:

Bloc 捕获事件,但您正在尝试发送连续的相同状态。试试yield StateTestHome();以上的另一个收益率

喜欢

yield StateIgnored(); // *****
yield StateTestHome();

编辑: 或者您可以删除 Equatable 抽象。

【讨论】:

  • StateHomeStateTestHome 是2 个不同的事件。所以我相信这是另外一回事。
【解决方案2】:

我发现了这个问题。 blocListener 仅侦听其直接child 的事件。我所做的是让它监听child(即childchild)内的子小部件触发的事件,这样就不会发生。

要解决此问题,请为直接 child 本身的 child 创建一个 blocListener

【讨论】:

    猜你喜欢
    • 2021-03-19
    • 2020-10-10
    • 2020-09-03
    • 2020-08-03
    • 2020-06-17
    • 2022-07-26
    • 2021-08-02
    • 2021-01-06
    • 2021-10-22
    相关资源
    最近更新 更多