реализация шаблона блока с API вызывает исключение «тип» Будущее «не является подтипом типа «Виджет»?»

#flutter #bloc

Вопрос:

Я пытаюсь реализовать шаблон блоков, в котором я использую класс репозитория, состоящий из всех методов, которые вызывают API. На другой стороне я собираюсь привести в исполнение BlocBuilder для отображения в представлении на основе блока государственный однако я получаю эту ошибку BlocBuilder<VehiclesBloc, VehiclesState=»»>(грязный, зависимостями: [_LocalizationsScope-[GlobalKey#df8d0]], состояние: _BlocBuilderBaseState<VehiclesBloc, VehiclesState=»»>#dba40): тип ‘будущее’ не является подтипом типа widget’?’

Я действительно не уверен, откуда берутся эти проблемы. вот несколько фрагментов кода.

это класс блока, который вызывает ошибку

   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();
 }
}
 

}

вот виджет с полным состоянием, который реализует конструктор блоков

    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,
                  ),
                ],
              ),
            ),
          )
        ],
      ),
    ));
  }   
 

Ответ №1:

Я думаю, что эта часть кода вызывает проблему:

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

Возможно, LoadingDialog.showLoadingDialog не возвращает виджет, а является просто функцией, которая возвращает будущее.

Для побочных эффектов (например, вы хотите отобразить диалоговое окно) вам следует использовать прослушиватели вместо выполнения такого кода внутри метода сборки. Вместо BlocBuilder этого просто используйте BlocConsumer и добавьте слушателя:

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

Еще немного информации о вашем коде:

  1. Вместо создания блока в качестве переменной в виджете с отслеживанием состояния используйте BlocProvider, который будет обрабатывать создание/удаление части вашего блока.
  2. VehiclesLoading Укажите состояние перед загрузкой данных, а не только в качестве «другого» случая. Таким образом, вы могли бы легко управлять поведением загрузки в своем пользовательском интерфейсе. Чтобы устранить вышеуказанные проблемы, просто следуйте документации: https://bloclibrary.dev/