【问题标题】:implementing bloc pattern with API cause an exception "type 'Future<dynamic>' is not a subtype of type 'Widget?'"使用 API 实现 bloc 模式会导致异常“类型 'Future<dynamic>' 不是类型 'Widget?' 的子类型”
【发布时间】:2021-10-01 03:02:25
【问题描述】:

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

我真的不确定问题出在哪里。这是代码的一些sn-ps。

这是导致错误的 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,
                  ),
                ],
              ),
            ),
          )
        ],
      ),
    ));
  }   

【问题讨论】:

    标签: flutter bloc


    【解决方案1】:

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

    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/

    【讨论】:

      猜你喜欢
      • 2020-09-11
      • 2023-03-27
      • 1970-01-01
      • 2019-08-18
      • 2023-03-30
      • 1970-01-01
      • 2021-02-17
      • 2021-10-21
      相关资源
      最近更新 更多