dart UI上未正确更新的复选框列表(Flutter BLOC)

xe55xuns  于 9个月前  发布在  Flutter
关注(0)|答案(2)|浏览(122)

我是第一次在我的应用程序中使用BLOC模式,我遇到了很多问题。
对于我的问题,我有一个布尔值列表(复选框)问题是,当我点击框时,有时它们会更新(正确的行为),有时它们不会更新(错误的行为)
在单击多次之前,复选框不会更改
Cubit等级

class FilterCubit extends Cubit<FilterState> {
  FilterCubit() : super(const FilterInitial());

  int sortByGV = 0;

  void onSortByClick(int index) {
    sortByGV = index;
    emit(OnSortByState(index));
  }

  List<bool> choiceSportsList = [];

  void fillChoiceSportsList(int length) {
    for (int i = 0; i < length; i++) {
      choiceSportsList.add(false);
    }
  }

  void onChoiceSportClick(int index) {
    if (choiceSportsList[index]) {
      choiceSportsList[index] = false;
      emit(const OnChoiceSportState(false));
    } else {
      choiceSportsList[index] = true;
      emit(const OnChoiceSportState(true));
    }
  }
}

字符串
State类

sealed class FilterState extends Equatable {
  const FilterState();

  @override
  List<Object?> get props => [];
}

final class FilterInitial extends FilterState {
  const FilterInitial();

  @override
  List<Object?> get props => [];
}

final class OnSortByState extends FilterState {
  final int index;
  const OnSortByState(this.index);

  @override
  List<Object?> get props => [index];
}

class OnChoiceSportState extends FilterState {
  final bool val;
  const OnChoiceSportState(this.val);

  @override
  List<Object?> get props => [val];
}


UI

showFilterBottomSheetComponent({double? heightFactor}) {
  sl<FilterCubit>().fillChoiceSportsList(10);

  return showModalBottomSheet<void>(
    context: sl<NavigationService>().navigatorKey.currentContext!,
    isScrollControlled: true,
    builder: (BuildContext context) {
      List<String> sports = [
        'Padel',
        'Soccer',
        'Basketball',
        'Tennis',
        'Padbol',
        'Pickleball',
        'Volleyball',
        'Badminton',
        'Squash',
        'Cricket'
      ];

      return FractionallySizedBox(
        heightFactor: heightFactor ?? 0.85,
        child: BlocProvider(
          create: (context) => sl<FilterCubit>(),
          child: SafeArea(
            child: Padding(
              padding:
                  EdgeInsets.all(AppPadding.p24).copyWith(top: AppPadding.p16),
              child: FilterChooseSportBody(data: sports),
            ),
          ),
        ),
      );
    },
  );
}

class FilterChooseSportBody extends StatelessWidget {
  const FilterChooseSportBody({
    super.key,
    required this.data,
  });

  final List<String> data;

  @override
  Widget build(BuildContext context) {
    final filterC = BlocProvider.of<FilterCubit>(context, listen: true);

    return Column(
      children: [
        for (int i = 0; i < data.length; i++)
          CheckBoxListTileComponent(
            title: data[i],
            value: filterC.choiceSportsList[i],
            onChanged: (value) {
              filterC.onChoiceSportClick(i);
            },
            smallHeight: true,
            style: getBodyMedium(),
          ),
      ],
    );
  }
}


在提供程序中,我有notifyListeners();
我是否需要在块中创建一个状态并每次都发出它?
谢谢.

yqkkidmi

yqkkidmi1#

你似乎忽略了你需要一个BlocBuilder,这样你的构建就可以对来自你的BLoC(或Cubit)的emit修改做出React。
您可以查看第一个tutorial来了解如何使用BLoCs和Cubit。
你对腕尺的选择,以及什么进入腕尺,什么离开腕尺,在我看来有点奇怪,所以我不会试图把一个解决方案融入其中。
根据我对模式的了解,你有一个BLoC,而不是一个cubit,因为你有结构化的数据,而不仅仅是一个简单的值,比如int。你的数据包括一个完整的数据列表,一个过滤的数据列表和选定的数据(如果有的话)。这三个东西应该保存在你的BLoC中,而不是你的UI中,它们应该在你的发射状态中。

bxjv4tth

bxjv4tth2#

我用下面的代码解决了这个问题。
首先,我删除了state类,并将其替换为List
然后Cubit类如下所示:

List<String> sports = [
  'Padel',
  'Soccer',
  'Basketball',
  'Tennis',
  'Padbol',
  'Pickleball',
  'Volleyball',
  'Badminton',
  'Squash',
  'Cricket',
];

class FilterCubit extends Cubit<List<FilterModel>> {
  FilterCubit() : super([]);

  void fillSport() {
    for (var e in sports) {
      final data = FilterModel(name: e, isActive: false);
      state.add(data);
      emit(state);
    }
  }

  void onChanged(Object? value, int index) {
    state[index].isActive = !state[index].isActive;

    emit([...state]);
  }
}

字符串
UI小部件

class FilterChooseSportBody extends StatefulWidget {
  const FilterChooseSportBody({super.key});

  @override
  State<FilterChooseSportBody> createState() => _FilterChooseSportBodyState();
}

class _FilterChooseSportBodyState extends State<FilterChooseSportBody> {
  @override
  void initState() {
    if (sl<FilterCubit>().state.isEmpty) {
      sl<FilterCubit>().fillSport();
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<FilterCubit, List<FilterModel>>(
      builder: (context, state) {
        return Column(
          children: [
            for (int i = 0; i < state.length; i++)
              CheckBoxListTileComponent(
                title: sl<FilterCubit>().state[i].name,
                value: state[i].isActive,
                onChanged: (value) {
                  sl<FilterCubit>().onChanged(value, i);
                },
                smallHeight: true,
                style: getBodyMedium(),
              ),
          ],
        );
      },
    );
  }
}


在上面的小部件树中,我添加了BlocProvider.value not BlocProvider
BlocProvider.value(value:cubit-here,child:..)

相关问题