【发布时间】:2020-02-18 12:10:46
【问题描述】:
我正在使用 Flutter BLoC 包来管理我的应用程序的状态,但自从上次包更新 (v0.22.1) 以来,我有一个奇怪的行为。
简单来说,我在PositionBloc 的EventsBloc 状态上有一个StreamSubscription 侦听器,但是当我从PositionBloc 添加一个事件时,侦听器不起作用。
最奇怪的是,我第一次从EventsBloc添加事件监听器工作,但之后似乎完全被忽略了。
这是我的构建树:
main.dart: 这里我展示的是主页或者基于认证的登录页面。 AuthenticationBloc 和 MoviesBloc 不重要,或者 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:这是一个用于管理TabBarView 的StatefulWidget,在这里我将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。这是一个很奇怪的情况,能帮帮我吗?
【问题讨论】: