I’m using the BloC pattern for the first time in my App.
And I am having multiple of problems with it.
For my Question i have a list of boolean ( Checkboxes )
The problem is when I click on the boxes sometimes they updated ( the correct behavior )
sometimes they does not updated ( wrong behavior )
The check box does not change until I click multiple times
Cubit Class
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 Class
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(),
),
],
);
}
}
In provider I have notifyListeners();
Do I need in bloc to create a state and emit it for each time??
Thanks.
2
Answers
I solved the problem with the following code.
First i removed the state class and replace it with List
Then the Cubit class like the following:
the UI widget
and in the above widget tree i added BlocProvider.value not BlocProvider
BlocProvider.value(value: cubit-here, child: .. )
You seem to have missed that you need a
BlocBuilder
, so your build can react to changesemit
ed from your BLoC (or Cubit).You can look at the first tutorial to check out how to use BLoCs and Cubit.
Your choice of Cubit and what goes into the cubit and what goes outside looks a little weird to me, so I will not try to fit a solution into this.
From what I know about the pattern, you have a BLoC, not a cubit, since you have structured data, not just one simple value like an
int
. Your data consists of a full list of data, a filtered list of data and the selected data (if any). Those three things should be held in your BLoC, not your UI, and those should be in your emitted states.