FLUTTER -BLOC不更新状态,即使使用copyWith()和equatable

lf3rwulv  于 2023-05-23  发布在  Flutter
关注(0)|答案(2)|浏览(171)

我已经创建了一个单选按钮类似的功能事件,用户可以一次只选择单个元素。但是当我触发事件选择值时,它不会更新状态,但是列表会更新。
这是我的块文件

class SlotsTabbarBloc extends Bloc<SlotsTabbarEvent, SlotsTabbarState> {

 SlotsTabbarSuccessState slotsTabbarSuccess =
      SlotsTabbarSuccessState(slotData: const [], enableButton: true);

 SlotsTabbarBloc(
    this.slotsUsecase,
  ) : super(SlotsTabbarInitial()) {
    SlotsTabbarLoading();

 on<SelectAvailablePanelRadioButtonEvent>(
      _selectAvailablePanelRadioButtonEvent,
    );
  }
Future<void> _selectAvailablePanelRadioButtonEvent(
    SelectAvailablePanelRadioButtonEvent event,
    Emitter<SlotsTabbarState> emit,
  ) async {
    bool isAvailableSlotRadioEnabled = false;

    for (int i = 0; i < event.dummyData.length; i++) {
      event.dummyData[i].isSelected =
          i == event.index ? isAvailableSlotRadioEnabled = true : false;
    }

    slotsTabbarSuccess = slotsTabbarSuccess.copyWith(
      isAvailableSlotRadioEnabled: isAvailableSlotRadioEnabled,
      availableSlotEntity: event.availableSlotEntity,
      dummyData: event.dummyData,
    );
    emit(slotsTabbarSuccess);
  }
}

这是事件类

class SelectAvailablePanelRadioButtonEvent extends SlotsTabbarEvent {
  bool isAvailableSlotRadioEnabled;
  final int index;
  final AvailableSlotEntity availableSlotEntity;
  final List<DummyData> dummyData;
    final List<InterviewSlotDtoListEntity> slotData;
  SelectAvailablePanelRadioButtonEvent({
    required this.isAvailableSlotRadioEnabled,
    required this.availableSlotEntity,
    required this.index,
    required this.dummyData,
    required this.slotData,
  });
}

这是国家级的

class SlotsTabbarSuccessState extends SlotsTabbarState {
  final List<InterviewSlotDtoListEntity> slotData;
  final AvailableSlotEntity? availableSlotEntity;
  final SpecificBookedCancelledSlotDetailsEntity?
      specificBookedCancelledSlotDetailsEntity;

  final String reasonForCancellationEnum;
  final String cancellationReason;
  final List<Map<String, dynamic>>? radioMap;
  final bool enableButton;
  final bool isRadioButtonSelected;
  final bool isAvailableSlotRadioEnabled;
  bool isBookedResponseTrue;
  bool isCancelledResponseTrue;
  bool markSlotAvailable;

  final List<DummyData>? dummyData;

  SlotsTabbarSuccessState({
    this.dummyData,
    required this.slotData,
    this.specificBookedCancelledSlotDetailsEntity,
    this.reasonForCancellationEnum = 'CANDIDATE_CANCEL',
    this.availableSlotEntity,
    this.radioMap,

    // this.enableButton = true,
    this.enableButton = true,
    this.isAvailableSlotRadioEnabled = true,
    this.isRadioButtonSelected = false,
    this.isBookedResponseTrue = false,
    this.isCancelledResponseTrue = false,
    this.markSlotAvailable = false,
    this.cancellationReason = '',
  });

  SlotsTabbarSuccessState copyWith({
    final List<DummyData>? dummyData,
    String? cancellationReason,
    List<InterviewSlotDtoListEntity>? slotData,
    AvailableSlotEntity? availableSlotEntity,
    SpecificBookedCancelledSlotDetailsEntity?
        specificBookedCancelledSlotDetailsEntity,
    String? reasonForCancellationEnum = 'CANDIDATE_CANCEL',
    List<Map<String, dynamic>>? radioMap,
    bool? isBookedResponseTrue = false,
    bool? isCancelledResponseTrue = false,
    bool? markSlotAvailable = false,
    bool? isRadioButtonSelected = false,
    bool? isAvailableSlotRadioEnabled,
    //bool? enableButton ,
    bool? enableButton,
  }) {
    return SlotsTabbarSuccessState(
      dummyData: dummyData ?? this.dummyData,
      cancellationReason: cancellationReason ?? this.cancellationReason,
      radioMap: radioMap ?? this.radioMap,
      isAvailableSlotRadioEnabled:
          isAvailableSlotRadioEnabled ?? this.isAvailableSlotRadioEnabled,
      enableButton: enableButton ?? this.enableButton,
      isRadioButtonSelected:
          isRadioButtonSelected ?? this.isRadioButtonSelected,
      markSlotAvailable: markSlotAvailable ?? this.markSlotAvailable,
      reasonForCancellationEnum:
          reasonForCancellationEnum ?? this.reasonForCancellationEnum,
      slotData: slotData ?? this.slotData,
      specificBookedCancelledSlotDetailsEntity:
          specificBookedCancelledSlotDetailsEntity ??
              this.specificBookedCancelledSlotDetailsEntity,
      availableSlotEntity: availableSlotEntity ?? this.availableSlotEntity,
      isBookedResponseTrue: isBookedResponseTrue ?? this.isBookedResponseTrue,
      isCancelledResponseTrue:
          isCancelledResponseTrue ?? this.isCancelledResponseTrue,
    );
  }

  @override
  List<Object> get props => [
        slotData,
        reasonForCancellationEnum,
        isBookedResponseTrue,
        isCancelledResponseTrue,
        markSlotAvailable,
        enableButton,
        isAvailableSlotRadioEnabled,
        isRadioButtonSelected,
        cancellationReason,
      ];
}

下面是我在UI中调用块的方法。每当我点击单选按钮时,它应该触发事件,事件应该发出状态。事件被触发,但UI未在屏幕上更新。刷新屏幕后会更新。

import 'package:auto_route/auto_route.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class DummyData {
  final String name;
  final String designation;
  bool isSelected = false;
  DummyData(
      {required this.name,
      required this.designation,
      required this.isSelected});
}

class AvailableOnClickWidget extends StatelessWidget {
  final String slotStartTime;
  final String slotEndTime;
  final bool showCheckBox;
  final List<InterviewSlotDtoListEntity> slotData;
  final String levelId;
  final String techStackId;
  bool isRadioButtonEnabled;

  AvailableOnClickWidget({
    super.key,
    required this.slotData,
    required this.slotStartTime,
    required this.slotEndTime,
    required this.showCheckBox,
    required this.isRadioButtonEnabled,
    required this.techStackId,
    required this.levelId,
  });
  TextEditingController candidateNameContoller = TextEditingController();
  // List<DummyData> dummyData = [
  //   DummyData(name: 'name', designation: 'designation', isSelected: false),
  //   DummyData(name: 'name', designation: 'designation', isSelected: false),
  //   DummyData(name: 'name', designation: 'designation', isSelected: false),
  //   DummyData(name: 'name', designation: 'designation', isSelected: false),
  // ];

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => Injector.resolve<SlotsTabbarBloc>(),
      child: BlocBuilder<SlotsTabbarBloc, SlotsTabbarState>(
        builder: (context, state) {
          if (state is SlotsTabbarInitial) {
            BlocProvider.of<SlotsTabbarBloc>(context).add(
              GetSpecificAvailableSlotDetailsEvent(
                slotData: slotData,
                fromTime: slotData[0].interviewSlotTimeDTOList[0].fromTime!,
                toTime: slotData[0].interviewSlotTimeDTOList[0].toTime!,
                slotDate: slotData[0].date!,
                interviewLevelId: levelId,
                techStackId: techStackId,
              ),
            );
            return const Center(
              child: CircularProgressIndicator(),
            );
          } else if (state is SlotsTabbarSuccessState) {
            if (state.isBookedResponseTrue) {
              CustomBotToastWidget.showToastWidget(
                context: context,
                onProgressBarCompletion: () {},
                toastMessage: StringConstants.slotMarkedAsBooked,
                showLinearProgressIndicator: false,
                showToastActionButton: false,
                cancelOnTap: () {
                  BotToast.cleanAll();
                },
              );
            }
            return SizedBox(
              height: MediaQuery.of(context).size.height * 0.95,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  24.verticalSpace,
                  TitleWithCancelButtonWidget(
                    title:
                        '${state.availableSlotEntity!.slotDate}, $slotStartTime - $slotEndTime',
                    textStyle: TextStyleConstants.s14w600c101828fMontserrat,
                  ),
                  40.verticalSpace,
                  Flexible(
                    fit: FlexFit.loose,
                    child: ListView.separated(
                      shrinkWrap: true,
                      padding: EdgeInsets.zero,
                      itemBuilder: (context, index) {
                        return AvailableOnClickPopUpListTile(
                            radioOnTap: () {
                              BlocProvider.of<SlotsTabbarBloc>(context).add(
                                SelectAvailablePanelRadioButtonEvent(
                                  slotData: state.slotData,
                                  availableSlotEntity:
                                      state.availableSlotEntity!,
                                  isAvailableSlotRadioEnabled:
                                      state.dummyData![index].isSelected,
                                  index: index,
                                  dummyData: state.dummyData!,
                                ),
                              );
                            },
                            imageUrl:
                                "https://lh3.googleusercontent.com/a/AEdFTp439zX_GEWqClFIwDVMbf8eUuCvqcLvjdiQcslZ=s96-c",
                            title: state.dummyData![index].name,
                            subtitle: state.dummyData![index].designation,
                            chipContainerText: state.dummyData![index].name,
                            isRadioButtonEnabled:
                                state.dummyData![index].isSelected
                            // ==
                            //     state.isAvailableSlotRadioEnabled,
                            //,
                            );
                        // return AvailableOnClickPopUpListTile(
                        //   imageUrl: state.availableSlotEntity!
                        //       .slotUserDetailList[0].imageUrl,
                        //   title:
                        //       '${state.availableSlotEntity!.slotUserDetailList[0].firstName} ${state.availableSlotEntity!.slotUserDetailList[0].lastName}',
                        //   subtitle: state.availableSlotEntity!
                        //       .slotUserDetailList[0].designation,
                        //   chipContainerText: state.availableSlotEntity!
                        //       .slotUserDetailList[0].levelOfInterview,
                        //   isRadioButtonEnabled:
                        //       state.isAvailableSlotRadioEnabled,
                        //   radioOnTap: () {
                        //     BlocProvider.of<SlotsTabbarBloc>(context).add(
                        //       SelectAvailablePanelRadioButtonEvent(
                        //         availableSlotEntity: state.availableSlotEntity!,
                        //         isAvailableSlotRadioEnabled: state
                        //             .availableSlotEntity!
                        //             .slotUserDetailList[0]
                        //             .isSelected,
                        //       ),
                        //     );
                        //   },
                        // );
                      },
                      separatorBuilder: (context, index) {
                        return 32.verticalSpace;
                      },
                      itemCount: state.dummyData!.length,
                      //    state.availableSlotEntity!.slotUserDetailList.length,
                    ),
                  ),
                  40.verticalSpace,
                  ColumnWithHeadingTextFieldAndIsmFilledButton(
                    reasonForCancellationController: candidateNameContoller,
                    isAvailableOnClickWidget: true,
                    isCancelledOnClickWidget: false,
                    onPressed: () {
                      BlocProvider.of<SlotsTabbarBloc>(context).add(
                        MarkAsBookedEvent(
                          candidateName: candidateNameContoller.text,
                          interviewLevelId: levelId,
                          techStackId: techStackId,
                          slotId: state.availableSlotEntity!
                              .slotUserDetailList[0].slotId,
                        ),
                      );

                      context.router.pop();
                    },
                    heading:
                        '${StringConstants.candidateName}${StringConstants.asterisk}',
                    maxLines: 1,
                    checkBoxOnChanged: (value) {},
                    textFieldOnChange: (value) {
                      BlocProvider.of<SlotsTabbarBloc>(context).add(
                        CandidateNameChangedEvent(
                          candidateName: candidateNameContoller.text,
                          enableButton: state.enableButton,
                        ),
                      );
                    },
                    checkBoxBooleanValue: true,
                    ismFilledButtonText: StringConstants.markAsBooked,
                    isIsmButtonValid: state.enableButton,
                    showCheckBox: showCheckBox,
                  ),
                  24.verticalSpace,
                ],
              ),
            );
          }
          return const SizedBox.shrink();
        },
      ),
    ).symmetricHorizontalPadding(16);
  }
}
z31licg0

z31licg01#

我不知道这是否有效,但试试这个:在SlotsTabbarBloc_selectAvailablePanelRadioButtonEvent函数结束时更改此:

slotsTabbarSuccess = slotsTabbarSuccess.copyWith(
    isAvailableSlotRadioEnabled: isAvailableSlotRadioEnabled,
    availableSlotEntity: event.availableSlotEntity,
    dummyData: event.dummyData,
);
emit(slotsTabbarSuccess);

对此:

emit(slotsTabbarSuccess.copyWith(
    isAvailableSlotRadioEnabled: isAvailableSlotRadioEnabled,
    availableSlotEntity: event.availableSlotEntity,
    dummyData: event.dummyData,
));

也从AvailableOnClickWidget中删除BlocProvider,并将其添加到MaterialApp之前的main.dart,类似于以下内容:

MultiBlocProvider(
    providers: [
        BlocProvider<SlotsTabbarBloc>(
            create: (context) => SlotsTabbarBloc(),
        ),
     ],
     child: const MaterialApp(
         ...
     ),
 ),
gv8xihay

gv8xihay2#

添加发射和完美的工作。我不知道为什么

on<InternetGainEvent>((result, emit) => emit(InternetGainState()));
on<InternetLostEvent>((result, emit) => emit( InternetLostState()));

相关问题