【问题标题】:bottom sheet is showing repeatedly once event triggred using bloc一旦使用 bloc 触发事件,底页就会重复显示
【发布时间】:2021-11-12 09:28:17
【问题描述】:

我是一个新手,正在学习如何使用冻结的 bloc。当用户单击浮动操作按钮时,我创建了一个底部工作表,底部工作表出现。当我单击以选择一个收音机时,底部表包含文本字段和三个单选组,底部表再次像此 GIF 一样弹出。 https://drive.google.com/file/d/1iU06adGcwjEaw9z2LsmO5xS24CC6OQfT/view?usp=sharing

集团是:

class NoteBloc extends Bloc<NoteEvent, NoteState> {
  NoteBloc() : super(NoteState.initial());

  @override
  Stream<NoteState> mapEventToState(
    NoteEvent event,
  ) async* {
    yield* event.map(
      addNewNoteButtonEvent: (AddNewNoteButtonEvent e) async* {
          yield state.copyWith(
            isAddNewNoteButtonClickedState: e.isClickedEvent,
          );
      },
      radioEvent: (RadioEvent e) async* {
        yield state.copyWith(radioGroupState: e.value);
      },
      textInputEvent: (TextInputEvent e) async* {
        yield state.copyWith(textInputState: Note(value: e.value));
      },
    );
  }
}

事件是:

class NoteEvent with _$NoteEvent {
  const factory NoteEvent.addNewNoteButtonEvent(
      {required bool isClickedEvent}) = AddNewNoteButtonEvent;
  const factory NoteEvent.radioEvent({required int value}) = RadioEvent;
  const factory NoteEvent.textInputEvent({required String value}) =
      TextInputEvent;
}

状态是:

class NoteState with _$NoteState {
  const factory NoteState({
    // required bool showSaveIconState,
    required int radioGroupState,
    required bool isAddNewNoteButtonClickedState,
    required Note textInputState,
  }) = _NoteState;
  // initialize every state
  factory NoteState.initial() => NoteState(
        radioGroupState: 1,
        isAddNewNoteButtonClickedState: false,
        textInputState: Note(value: ''),
      );
}

首页代码为:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
    return BlocConsumer<NoteBloc, NoteState>(
      listener: (context, state) {
        // if (state is AddNoteClickedState) {
        if (state.isAddNewNoteButtonClickedState) {
          
          // show navigator
          _scaffoldKey.currentState!
              .showBottomSheet((context) => const AddNewNoteBottomSheet())
              .closed
              .then(
            (value) {
              // Change state
              // to tell the bloc that
              // the bottom sheet is closed
              context.read<NoteBloc>().add(
                    const NoteEvent.addNewNoteButtonEvent(
                      isClickedEvent: false, // !state.isAddNewNoteClickedState,
                    ),
                  );
            },
          );
        }
      },
      builder: (context, state) {
        return DefaultTabController(
          length: 3,
          child: Scaffold(
            key: _scaffoldKey,
            // add note float action button
            floatingActionButton: InkWell(
              onTap: () {
                // make button clicked
                // to open the bottom sheet
                context.read<NoteBloc>().add(
                      const NoteEvent.addNewNoteButtonEvent(
                        isClickedEvent: true, //!state.isAddNewNoteClickedState,
                      ),
                    );
                // print(state);
              },
              // for float action button
              // icon shape
              child: Container(
                clipBehavior: Clip.antiAliasWithSaveLayer,
                height: 11.h,
                width: 10.h,
                decoration: BoxDecoration(
                  shape: BoxShape.rectangle,
                  borderRadius: BorderRadius.all(Radius.circular(1.w)),
                  color: const Color(accentColor),
                ),
                // add note icon
                child: Icon(
                  state.isAddNewNoteButtonClickedState ? Icons.save : Icons.add,
                  color: const Color(whiteColor),
                  size: 9.h,
                ),
              ),
        );
      },
    );
  }
}

AddNewNoteBottomSheet 代码为:

// For adding new note
class AddNewNoteBottomSheet extends StatelessWidget {
  const AddNewNoteBottomSheet();

  @override
  Widget build(BuildContext context) {
    TextEditingController _textEditingController = TextEditingController();
    return Container(
      // Contains all
      // bottom sheet components
      child: Column(
              children: [
          // bottom sheet body
          Expanded(
            child: SingleChildScrollView(
              child: BlocBuilder<NoteBloc, NoteState>(
                builder: (context, state) {
                  // print("Helllo ${state.maybeMap(orElse: (){},radioClickState: (stat)=>stat.value)}");
                  return Column(
                    children: [
                      
                      // Today Radio
                      ListTile(
                        title: Text(
                          AppLocalizations.of(context)!.homeTodayTapTitle,
                          style: Theme.of(context)
                              .tabBarTheme
                              .unselectedLabelStyle,
                        ),
                        contentPadding: const EdgeInsets.all(0),
                        autofocus: true,
                        leading: Radio<int>(
                          value: 1,
                          //get group value
                          groupValue: state.radioGroupState,
                          onChanged: (value) {
                            // tell bloc i click you
                            context
                                .read<NoteBloc>()
                                .add(NoteEvent.radioEvent(value: value!));
                          },
                        ),
                      ),
                      // Tomorrow Radio
                      ListTile(
                        contentPadding: const EdgeInsets.all(0),
                        title: Text(
                          AppLocalizations.of(context)!.homeTomorrowTapTitle,
                          style: Theme.of(context)
                              .tabBarTheme
                              .unselectedLabelStyle,
                        ),
                        leading: Radio<int>(
                          value: 2,
                          //get group value
                          groupValue: state.radioGroupState,
                          onChanged: (value) {
                            // tell bloc i click you
                            context.read<NoteBloc>().add(
                                  NoteEvent.radioEvent(value: value!),
                                );
                          },
                        ),
                      ),
                      // Some Day Radio
                      ListTile(
                        contentPadding: const EdgeInsets.all(0),
                        title: Text(
                          AppLocalizations.of(context)!.homeSomeDayTapTitle,
                          style: Theme.of(context)
                              .tabBarTheme
                              .unselectedLabelStyle,
                        ),
                        leading: Radio<int>(
                          value: 3,
                          //get group value
                          groupValue: state.radioGroupState,

                          onChanged: (value) {
                            // tell bloc i click you
                            context.read<NoteBloc>().add(
                                  NoteEvent.radioEvent(value: value!),
                                );
                          },
                        ),
                      ),
                    ],
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: flutter bloc flutter-bloc freezed flutter-freezed


    【解决方案1】:

    问题定义:出现此问题是因为您在 bloc 上使用了 state.copyWith。当您使用 copyWith 时,即使您不更新 isAddNewNoteButtonClickedState 变量,如果您不更改它,您的状态也会保留该值(设置后保持为真,如果不更改则永远不会更改)。因为在 copyWith 方法上,更新逻辑的工作方式类似于;

    YourState copyWith(bool isAddNewNoteButtonClickedState) {
       return YourState(isAddNewNoteButtonClickedState: isAddNewNoteButtonClickedState ?? this. isAddNewNoteButtonClickedState,)
    }
    

    当您产生另一个状态时,isAddNewNoteButtonClickedState 保持为真,并且您的侦听器显示另一个模式,因为您的 isAddNewNoteButtonClickedState 没有改变。

    解决方案:您可以通过(将isAddNewNoteButtonClickedState: false添加到其他状态)来解决此问题:

        class NoteBloc extends Bloc<NoteEvent, NoteState> {
      NoteBloc() : super(NoteState.initial());
    
      @override
      Stream<NoteState> mapEventToState(
        NoteEvent event,
      ) async* {
        yield* event.map(
          addNewNoteButtonEvent: (AddNewNoteButtonEvent e) async* {
              yield state.copyWith(
                isAddNewNoteButtonClickedState: e.isClickedEvent,
              );
          },
          radioEvent: (RadioEvent e) async* {
            yield state.copyWith(radioGroupState: e.value, isAddNewNoteButtonClickedState: false);
          },
          textInputEvent: (TextInputEvent e) async* {
            yield state.copyWith(textInputState: Note(value: e.value), isAddNewNoteButtonClickedState: false);
          },
        );
      }
    }
    

    补充说明: 由于您不是在整体中转换事件或做一些琐碎的事情,因此您可以使用 cubit 来简化您的状态管理和业务逻辑。

    【讨论】:

      猜你喜欢
      • 2016-07-31
      • 2020-12-11
      • 2012-09-13
      • 2013-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-26
      • 2023-03-26
      相关资源
      最近更新 更多