Flutter BLoC - StreamSubscription 不监听调度事件

Flutter BLoC - StreamSubscription not listen on dispatched event

我正在使用 Flutter BLoC 包来管理我的应用程序的状态,但是自上次包更新 (v0.22.1) 以来,我的行为很奇怪。

简单地说,我在 EventsBloc 中的 PositionBloc 状态上有一个 StreamSubscription 侦听器,但是当我从 PositionBloc 添加事件时,侦听器不起作用。 最奇怪的是,我第一次从 EventsBloc 添加事件时监听器工作,但之后似乎完全被忽略了。

这是我的构建树:

main.dart:这里我展示的是首页或者是基于认证的登录页面。 AuthenticationBlocMoviesBloc 并不重要,或者 LocalsBloc 重点是 PositionBloc

class App extends StatelessWidget {
  ...
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      builder: (context) => MoviesBloc()..add(LoadMovies()),
      child: MaterialApp(
        home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
          builder: (context, state) {
            if (state is Unauthenticated) {
              return Login(
                authenticationRepository: _authenticationRepository,
              );
            }
            if (state is Authenticated) {
              return MultiBlocProvider(
                providers: [
                  BlocProvider<LocalsBloc>(
                    builder: (context) => LocalsBloc()..add(LoadLocals()),
                  ),
                  BlocProvider<PositionBloc>(
                    builder: (context) => PositionBloc(
                      localsBloc: BlocProvider.of<LocalsBloc>(context),
                    ),
                  )
                ],
                child: Home(),
              );
            }
            return Splash();
          },
        ),
      ),
    );
  }
}

home.dart:这是管理TabBarViewStatefulWidget,这里我向小部件EventsCarousel提供EventsBloc。在 SearchBar 小部件中,我有调度事件的触发器,因此根据所选位置重建 EventsCarousel

class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
  ...
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: TabBarView(
          children: <Widget>[
            Stack(
              alignment: Alignment.topCenter,
              children: <Widget>[
                BlocProvider<EventsBloc>(
                  builder: (context) => EventsBloc(),
                  child: EventsCarousel(),
                ),
                Positioned(
                  child: SearchBar(),
                ),
              ],
            ),
            MoviesList(),
            Settings(),
          ],
          controller: _tabController,
        ),
      ),
      bottomNavigationBar: Material(
        child: TabBar(
          indicatorColor: Colors.deepOrange,
          tabs: <Tab>[
            Tab(
              icon: Icon(
                FontAwesomeIcons.home
              ),
            ),
            Tab(
              icon: Icon(
                FontAwesomeIcons.bullhorn,
              ),
            ),
            Tab(
              icon: Icon(
                FontAwesomeIcons.cogs,
              ),
            ),
          ],
          controller: _tabController,
        ),
      ),
    );
  }

search_bar.dart:这是一个 StatefulWidget 用于管理 _textController_focusNode。在这里,我有我的应用程序状态转换器。我使用 Flutter TypeAhead 包来构建搜索栏,我的搜索栏条目来自 LocalsBloc,我们在 main.dart 中看到。当我点击一个条目时,我将事件 UpdatePosition(local) 添加到 PositionBloc.

class _SearchBarState extends State<SearchBar> {
  ...
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PositionBloc, PositionState>(
      builder: (context, state) {
        if (state is PositionUpdated) {
          if (!_focusNode.hasFocus) {
            _textController.text = state.position.local.description;
          }

          return Container(
            decoration: BoxDecoration(
              color: Colors.white,
            ),
            width: MediaQuery.of(context).size.width * 0.75,
            child: TypeAheadField<Local>(
                getImmediateSuggestions: true,
                textFieldConfiguration: TextFieldConfiguration(
                  decoration: InputDecoration(
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.all(
                        Radius.circular(10.0),
                      ),
                    ),
                    hintText: "Inserisci una posizione",
                    contentPadding: EdgeInsets.all(15),
                  ),
                  focusNode: _focusNode,
                  controller: _textController,
                ),
                suggestionsCallback: (String pattern) {
                  return (BlocProvider.of<LocalsBloc>(context).state as LocalsLoaded)
                      .locals
                      .where(
                        (local) =>
                            local.description
                                .toLowerCase()
                                .contains(pattern.toLowerCase()),
                      )
                      .toList();
                },
                noItemsFoundBuilder: (context) {
                  return Text('Nessun risultato trovato');
                },
                itemBuilder: (context, Local suggestion) {
                  return Card(
                    child: ListTile(
                      title: Text(suggestion.description),
                      subtitle: Text(suggestion.town),
                      trailing: Icon(Icons.gps_not_fixed),
                    ),
                  );
                },
                onSuggestionSelected: (Local suggestionSelected) {
                  BlocProvider.of<PositionBloc>(context).add(
                    UpdatePosition(suggestionSelected),
                  );
                }),
          );
        } else {
          return Container();
        }
      },
    );
  }

我有事件和状态的标准 Bloc 样板,特别是 EventsBloc,正如我所说我有这个订阅:

EventsBloc({@required PositionBloc positionBloc})
  : assert(PositionBloc != null),
    _positionBloc = positionBloc {
positionSubscription = positionBloc.listen((state) {
  if (state is PositionUpdated) {
    add(LoadEvents(state.local));
  }
});

此侦听器在第一个小部件树构建后不起作用,但是当我从搜索栏中的条目选择中添加事件 UpdatePosition 时,PositionBloc 的状态发生变化并且事件正确映射到 PositionUpdated。这是一个很奇怪的情况,可以帮助我吗?

我刚刚注意到我在 CTORs 初始值设定项中为我的 PositionUpdated 状态错过了一个超级调用,因此没有调用侦听器。这是我的错误,我在调试中已经跟踪了三天。