我正在设计一个BlocBuilder
嵌套在另一个BlocBuilder
中的应用。
将事件调度到嵌套ServiceBloc
时,页面未按预期刷新:嵌套BlocBuiler.builder
未触发。
这种方法有什么问题?
在MVCE下面再现了问题。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:bloc/bloc.dart';
void main() async {
runApp(App());
}
class App extends StatefulWidget {
@override
AppState createState() {
return new AppState();
}
}
// AppBloc states
class ServicePage {}
class SearchState extends ServicePage {}
class AllServices extends ServicePage {}
// end of AppBloc states
// AppBloc events
class AppEvent {}
class EnableSearch extends AppEvent {}
class DisableSearch extends AppEvent {}
// end of AppBloc events
class AppBloc extends Bloc<AppEvent, ServicePage> {
@override
ServicePage get initialState => AllServices();
@override
Stream<ServicePage> mapEventToState(
ServicePage currentState, AppEvent event) async* {
if (event is EnableSearch) {
yield SearchState();
} else {
yield AllServices();
}
}
}
// ServiceBloc events
class ServiceEvent {}
class ServicesLoaded extends ServiceEvent {}
class ServiceFilter extends ServiceEvent {
String pattern;
ServiceFilter(this.pattern);
}
// end of ServiceBloc events
class ServiceBloc extends Bloc<ServiceEvent, List<String>> {
List<String> services = ["aa", "bb", "cc"];
@override
List<String> get initialState => services;
@override
Stream<List<String>> mapEventToState(
List<String> currentState, ServiceEvent event) async* {
if (event is ServiceFilter) {
yield services.where((service) => service.contains(event.pattern));
} else {
yield services;
}
}
}
class AppState extends State<App> {
final TextEditingController _filter = TextEditingController();
final AppBloc appBloc = AppBloc();
final ServiceBloc serviceBloc = ServiceBloc();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: BlocBuilder(
bloc: appBloc,
builder: (BuildContext context, ServicePage sts) {
var searchBar;
if (sts is AllServices) {
searchBar = AppBar(title: const Text('MVCE multi bloc'), actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {
appBloc.dispatch(EnableSearch());
},
),
]);
} else {
searchBar = AppBar(
title: TextField(
onSubmitted: (val) {
print("filter string: $val");
serviceBloc.dispatch(ServiceFilter(_filter.text));
},
controller: _filter,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search), hintText: 'Search...'),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
serviceBloc.dispatch(ServiceFilter(_filter.text));
appBloc.dispatch(DisableSearch());
}),
]);
}
return Scaffold(
appBar: searchBar,
body: ServicesWidget(serviceBloc));
}),
);
}
}
class ServicesWidget extends StatelessWidget {
final ServiceBloc bloc;
ServicesWidget(this.bloc);
@override
Widget build(BuildContext context) {
return BlocBuilder(
bloc: bloc,
builder: (BuildContext context, List<String> services) {
print("Rebuilding list view");
return ListView.builder(
itemCount: services.length,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 100,
child: Card(
child: Column(
children: <Widget>[
Text(services[index]),
],
)),
);
});
});
}
}
答案 0 :(得分:0)
该问题与BlocBuilder
的嵌套无关,而与mapEventToState
的实现有关:
Stream<List<String>> mapEventToState(
List<String> currentState, ServiceEvent event) async* {
if (event is ServiceFilter) {
yield services.where((service) => service.contains(event.pattern));
} else {
yield services;
}
}
service.where()
返回一个WhereIterable
,而不是字符串列表。
由于某种原因,我不知道,该异常被静默捕获,并且不会调用BlocBuilder的构建器小部件。
以下内容具体化了一个列表并使其成为多块示例:
Stream<List<String>> mapEventToState(
List<String> currentState, ServiceEvent event) async* {
if (event is ServiceFilter) {
yield services.where((service) => service.contains(event.pattern)).toList();
} else {
yield services;
}
}