Блок Flutter - кнопка не вызывает изменения состояния - PullRequest
0 голосов
/ 07 октября 2019

У меня есть main.dart со своими main_bloc.dart, main_event.dart и main_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()), из 1011 * будет 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 не перехватило событие изменения состояния.

Что мне здесь не хватает? Как я могу решить это?

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Bloc ловит событие, но вы пытаетесь отправить одно и то же состояние подряд. Попробуйте другой доход выше yield StateTestHome();

Как

yield StateIgnored(); // *****
yield StateTestHome();
0 голосов
/ 11 октября 2019

Я разобрался в проблеме. blocListener только слушает событие ДЛЯ его немедленного child. Я сделал так, чтобы он прослушивал события, запускаемые дочерним виджетом внутри child (child немедленного child), так что этого не произойдет.

для решения этой проблемыпроблема, создайте blocListener для этого child самого child.

...