首页 > 解决方案 > 使用 API 实现 bloc 模式会导致异常“type 'Future' 不是 'Widget?' 类型的子类型?

问题描述

我正在尝试实现 bloc 模式,其中我正在使用一个存储库类,该存储库类包含使用 API 进行调用的所有方法。另一方面,我正在实现 BlocBuilder 以根据 bloc 状态呈现视图但是我收到此错误 BlocBuilder<VehiclesBloc, VehiclesState>(dirty, dependencies: [_LocalizationsScope-[GlobalKey#df8d0]], state: _BlocBuilderBaseState<VehiclesBloc, VehiclesState >#dba40):“未来”类型不是“小部件?”类型的子类型

我真的不确定问题来自哪里。这是代码的一些片段。

这是导致错误的 bloc 类

  class VehiclesBloc extends Bloc<VehiclesEvent,VehiclesState>{
  VehiclesBloc(VehiclesState initialState) : super(initialState);

  @override
 Stream<VehiclesState> mapEventToState(VehiclesEvent event) async* {
 // TODO: implement mapEventToState
 if(event is LoadVehiclesList){
  yield* mapLoadEventToState(event);
 }
}

Stream<VehiclesState> mapLoadEventToState(LoadVehiclesList event) async* {
if(event is LoadVehiclesList){
  var response = await VehiclesService().getAll();
  if(response.IsSuccess){
   yield  VehiclesLoaded(response.Data);
  }else{
   yield VehiclesLoadingFailed(response.ErrorList.toString());
   }
  }else{
 yield VehiclesLoading();
 }
}

}

这是实现 Bloc Builder 的 Statefull 小部件

   class VehicleList extends StatefulWidget {
   const VehicleList({Key key}) : super(key: key);
   static const String routeName = "/VehicleList";
  //final ScrollController scrollController;

  @override
 _VehicleListState createState() => _VehicleListState();
 }

class _VehicleListState extends State<VehicleList> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
VehiclesBloc vehiclesBloc = 
VehiclesBloc(VehiclesLoading())..add(LoadVehiclesList());

@override
void initState() {
 // TODO: implement initState
  super.initState();
 //VehiclesService().getAll();
}

  @override
  void dispose() {
  // TODO: implement dispose
   vehiclesBloc.close();
   super.dispose();
  }

 @override
  Widget build(BuildContext context) {
  final isRtl = context.locale.languageCode == "ar";
  return Scaffold(
    key: _scaffoldKey,
    backgroundColor: kBackgroundColor,
    drawer: SideNavigationDrawer(),
    body: Container(
      child: Column(
        children: [
          SizedBox(
            height: 15,
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              IconButton(
                onPressed: () {
                  _scaffoldKey.currentState.openDrawer();
                },
                icon: Icon(
                  Icons.menu,
                  size: 35,
                  color: Colors.black,
                ),
              )
            ],
          ),
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  BlocBuilder<VehiclesBloc,VehiclesState>(
                    builder: (context, state) {
                      if (state is VehiclesLoaded) {
                       // return BuildListVehicle(state.lsVehicle);
                        return Center();
                      } else if (state is VehiclesLoadingFailed) {
                        return Center(
                          child: CustomErrorWidget(),
                        );
                      } else {
                        return Center(
                          child: LoadingDialog.showLoadingDialog(context,
                              text: ""),
                        );
                      }
                    },
                    cubit: vehiclesBloc,
                  ),
                ],
              ),
            ),
          )
        ],
      ),
    ));
  }   

标签: flutterbloc

解决方案


我认为这个代码部分会导致问题:

return Center(
  child: LoadingDialog.showLoadingDialog(context,text: ""),
);

可能LoadingDialog.showLoadingDialog不会返回 Widget,而只是返回 Future 的函数。

对于副作用(例如,您想显示对话框),您应该使用侦听器而不是在 build 方法中执行此类代码。而不是BlocBuilder,只需使用BlocConsumer并添加侦听器:

BlocConsumer<VehiclesBloc,VehiclesState>(
  listener: (context, state) {
    if (state is {your loading state}) {
      LoadingDialog.showLoadingDialog(context, text: "");
    }
  },
  builder: ...,
),

有关您的代码的更多见解:

  1. 不要在有状态的小部件中创建 BLoC 作为变量,而是使用 BlocProvider 来处理 BLoC 的创建/处置部分。
  2. 在加载数据之前产生VehiclesLoading状态,而不仅仅是“其他”情况。这样您就可以在 UI 中轻松处理加载行为。要解决上述问题,只需遵循文档:https ://bloclibrary.dev/

推荐阅读