【问题标题】:Flutter BLoC - StreamSubscription not listen on dispatched eventFlutter BLoC - StreamSubscription 不监听已调度的事件
【发布时间】:2020-02-18 12:10:46
【问题描述】:

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

简单来说,我在PositionBlocEventsBloc 状态上有一个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,在这里我将EventsBloc 提供给小部件EventsCarousel。在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 包来构建搜索栏,我的搜索栏的条目是从我们在main.dart 中看到的LocalsBloc 提供的。当我点击一个条目时,我会将事件 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 样板,特别是 EventBloc,因为我说过我有这个订阅:

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

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

【问题讨论】:

    标签: flutter bloc


    【解决方案1】:

    我刚刚注意到我错过了 CTOR 初始化程序中针对我的 PositionUpdated 状态的超级调用,因此未调用侦听器。这是我的错误,我在调试中跟踪了三天。

    【讨论】:

      猜你喜欢
      • 2020-04-29
      • 2021-02-17
      • 1970-01-01
      • 2020-03-26
      • 2021-02-20
      • 2020-03-23
      • 2023-03-24
      • 2019-10-24
      • 2019-12-06
      相关资源
      最近更新 更多