Flutter 多个bloc:如何嵌套BlocBuilder

Flutter 多个bloc:如何嵌套BlocBuilder,flutter,Flutter,我正在设计一个应用程序,其中一个BlocBuilder嵌套在另一个BlocBuilder中 将事件分派到嵌套的ServiceBlocbloc时,页面不会按预期刷新:嵌套的BlocBuiler.builder不会触发 这种方法有什么错 下面是一个重现问题的MVCE import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:bloc/bloc.dar

我正在设计一个应用程序,其中一个
BlocBuilder
嵌套在另一个
BlocBuilder

将事件分派到嵌套的
ServiceBloc
bloc时,页面不会按预期刷新:嵌套的
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]),
                    ],
                  )),
                );
              });
        });
  }
}
导入“包装:颤振/材料.省道”;
进口“包装:颤振团/颤振团.飞镖”;
导入“包:bloc/bloc.dart”;
void main()异步{
runApp(App());
}
类应用程序扩展StatefulWidget{
@凌驾
AppState createState(){
返回新的AppState();
}
}
//AppBloc国家
类ServicePage{}
类SearchState扩展ServicePage{}
类AllServices扩展ServicePage{}
//AppBloc状态结束
//AppBloc事件
类AppEvent{}
类EnableSearch扩展了appent{}
类DisableSearch扩展appent{}
//AppBloc事件结束
类AppBloc扩展了Bloc{
@凌驾
ServicePage get initialState=>AllServices();
@凌驾
流映射事件状态(
ServicePage当前状态,AppEvent事件)异步*{
如果(事件为EnableSearch){
屈服状态();
}否则{
产生所有服务();
}
}
}
//服务集团事件
类ServiceEvent{}
类ServicesLoaded扩展ServiceEvent{}
类ServiceFilter扩展ServiceEvent{
字符串模式;
ServiceFilter(此.pattern);
}
//ServiceBloc事件结束
类ServiceBloc扩展了Bloc{
列表服务=[“aa”、“bb”、“cc”];
@凌驾
List get initialState=>services;
@凌驾
流映射事件状态(
列出当前状态、服务事件(事件)异步*{
如果(事件为ServiceFilter){
其中((service)=>service.contains(event.pattern));
}否则{
收益服务;
}
}
}
类AppState扩展了状态{
最终文本编辑控制器_过滤器=文本编辑控制器();
最终AppBloc AppBloc=AppBloc();
最终ServiceBloc ServiceBloc=ServiceBloc();
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。红色,
),
主页:BlocBuilder(
集团:appBloc,
生成器:(BuildContext上下文,ServicePage sts){
var搜索栏;
如果(sts是所有服务){
searchBar=AppBar(标题:const Text('MVCE multi-bloc'),操作:[
图标按钮(
图标:图标(Icons.search),
已按下:(){
appBloc.dispatch(EnableSearch());
},
),
]);
}否则{
searchBar=AppBar(
标题:文本字段(
提交:(val){
打印(“过滤器字符串:$val”);
serviceBloc.dispatch(ServiceFilter(_filter.text));
},
控制器:_过滤器,
装饰:输入装饰(
前缀:Icon(Icons.search),hintText:“search…”,
),
行动:[
图标按钮(
图标:图标(Icons.close),
已按下:(){
serviceBloc.dispatch(ServiceFilter(_filter.text));
appBloc.dispatch(DisableSearch());
}),
]);
}
返回脚手架(
appBar:searchBar,
机构:ServicesWidget(serviceBloc));
}),
);
}
}
类ServicesWidget扩展了无状态小部件{
最终服务集团;
ServicesWidget(this.bloc);
@凌驾
小部件构建(构建上下文){
返回BlocBuilder(
集团:集团,,
生成器:(BuildContext上下文,列出服务){
打印(“重建列表视图”);
返回ListView.builder(
itemCount:services.length,
itemBuilder:(构建上下文,int索引){
返回大小框(
身高:100,
孩子:卡片(
子:列(
儿童:[
文本(服务[索引]),
],
)),
);
});
});
}
}

问题与
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;
  }
}
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;
  }
}