Flutter/Dart - 无法修改不可修改的地图错误
Flutter/Dart - Cannot modify unmodifiable map error
我用 Flutter bloc 创建了一个应用程序 package.Ive 创建了一个名为 learning_dashboard_screen 的屏幕,其中包含从服务器获取的列表。
在同一屏幕内,我有一个过滤器按钮,按下该按钮将使用底部 sheet 小部件显示过滤器屏幕。
要过滤的列表有不同的类别。
在 learning_dashboard_screen_state 屏幕中,我得到了一个名为 filteroptions 的地图,它的类型
Map>。此地图用于通过将地图与复选框小部件映射来填充复选框。
part of 'learning_dashboard_screen_bloc.dart';
class LearningDashboardScreenState extends Equatable {
static ScrollController controller = ScrollController();
final int courseLimit = 3;
final List<GPaginatedCoursesData_paginatedCourses_data> courses;
final DataRetrievalStatus initialCoursesStatus;
final Map<String, Map<String, dynamic>> filterOption;
Map<String, Map<String, dynamic>> getFilterOption() {
return filterOption;
}
final int currPage;
final bool hasNextPage;
final DataRetrievalStatus moreCoursesStatus;
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
this.filterOption = const {
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {"Sinhala": false, "English": false, "Tamil": false},
"Duration": {"6 Months": false, "8 Months": false, "1Year": false},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
}
},
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED});
@override
List<Object?> get props => [
courses,
filterOption,
initialCoursesStatus,
courseLimit,
currPage,
hasNextPage,
moreCoursesStatus
];
LearningDashboardScreenState copyWith(
{List<GPaginatedCoursesData_paginatedCourses_data>? course,
DataRetrievalStatus? courseStatus,
int? currPage,
bool? hasNextPage,
Map<String, Map<String, dynamic>>? filterOption,
DataRetrievalStatus? moreCourseStatus}) {
return LearningDashboardScreenState(
courses: course ?? this.courses,
filterOption: filterOption ?? this.filterOption,
initialCoursesStatus: courseStatus ?? this.initialCoursesStatus,
currPage: currPage ?? this.currPage,
hasNextPage: hasNextPage ?? this.hasNextPage,
moreCoursesStatus: moreCourseStatus ?? this.moreCoursesStatus);
}
ScrollController getScrollController() {
return controller;
}
}
我想要的是根据chackbox的值改变state中filteroption map的boolean值。为此,我所做的是,
1.I 在活动中创建了一个活动 class ,
class CheckBoxValueChangedEvent extends LearningDashboardScreenEvent {
String filterOption;
String filterValue;
bool isChecked;
CheckBoxValueChangedEvent({required this.filterOption,required this.filterValue,required
this.isChecked});
@override
List<Object?> get props => [];
}
我在按下复选框时调用了那个事件
CheckBox(
label: entry.key,
onChanged: (isChecked) {
context
.read<LearningDashboardScreenBloc>()
.add(CheckBoxValueChangedEvent(filterOption: widgetName, filterValue:
entry.key, isChecked: isChecked));
},
key: GlobalKey<CheckBoxState>(),
initValue: entry.value,
),
3.In bloc class 我编写了函数来更改状态 class 中的 bool 值并发出状态,
void _onCheckBoxValueChangedEvent(CheckBoxValueChangedEvent event,
Emitter<LearningDashboardScreenState> emit) {
Map<String, Map<String, dynamic>> filterOption = {};
filterOption=new Map<String, Map<String, dynamic>>.from(state.filterOption);
if (event.isChecked = true) {
filterOption[event.filterOption]![event.filterValue] = true;
} else {
filterOption[event.filterOption]![event.filterValue] = false;
}
emit(state.copyWith(filterOption: filterOption));
}
我的问题是当我勾选一个复选框时,
Error: Unhandled error Unsupported operation: Cannot modify unmodifiable map occurred in
Instance of 'LearningDashboardScreenBloc'.
问题是,当您将地图声明为 const
时,您无法修改地图。
在你的构造函数中 filterOption
有一个默认值 const
:
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
this.filterOption = const {
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {"Sinhala": false, "English": false, "Tamil": false},
"Duration": {"6 Months": false, "8 Months": false, "1Year": false},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
},
},
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED}
);
一个可能的解决方法是在初始化列表中定义映射文字,而不是作为默认参数(这样它就不需要是常量)。
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
Map<String, Map<String, dynamic>>? filterOption,
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED}
): this.filterOption = filterOption ??
{
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {
"Sinhala": false,
"English": false,
"Tamil": false
},
"Duration": {
"6 Months": false,
"8 Months": false,
"1Year": false
},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
}
};
我用 Flutter bloc 创建了一个应用程序 package.Ive 创建了一个名为 learning_dashboard_screen 的屏幕,其中包含从服务器获取的列表。 在同一屏幕内,我有一个过滤器按钮,按下该按钮将使用底部 sheet 小部件显示过滤器屏幕。
要过滤的列表有不同的类别。
在 learning_dashboard_screen_state 屏幕中,我得到了一个名为 filteroptions 的地图,它的类型
Map
part of 'learning_dashboard_screen_bloc.dart';
class LearningDashboardScreenState extends Equatable {
static ScrollController controller = ScrollController();
final int courseLimit = 3;
final List<GPaginatedCoursesData_paginatedCourses_data> courses;
final DataRetrievalStatus initialCoursesStatus;
final Map<String, Map<String, dynamic>> filterOption;
Map<String, Map<String, dynamic>> getFilterOption() {
return filterOption;
}
final int currPage;
final bool hasNextPage;
final DataRetrievalStatus moreCoursesStatus;
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
this.filterOption = const {
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {"Sinhala": false, "English": false, "Tamil": false},
"Duration": {"6 Months": false, "8 Months": false, "1Year": false},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
}
},
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED});
@override
List<Object?> get props => [
courses,
filterOption,
initialCoursesStatus,
courseLimit,
currPage,
hasNextPage,
moreCoursesStatus
];
LearningDashboardScreenState copyWith(
{List<GPaginatedCoursesData_paginatedCourses_data>? course,
DataRetrievalStatus? courseStatus,
int? currPage,
bool? hasNextPage,
Map<String, Map<String, dynamic>>? filterOption,
DataRetrievalStatus? moreCourseStatus}) {
return LearningDashboardScreenState(
courses: course ?? this.courses,
filterOption: filterOption ?? this.filterOption,
initialCoursesStatus: courseStatus ?? this.initialCoursesStatus,
currPage: currPage ?? this.currPage,
hasNextPage: hasNextPage ?? this.hasNextPage,
moreCoursesStatus: moreCourseStatus ?? this.moreCoursesStatus);
}
ScrollController getScrollController() {
return controller;
}
}
我想要的是根据chackbox的值改变state中filteroption map的boolean值。为此,我所做的是,
1.I 在活动中创建了一个活动 class ,
class CheckBoxValueChangedEvent extends LearningDashboardScreenEvent {
String filterOption;
String filterValue;
bool isChecked;
CheckBoxValueChangedEvent({required this.filterOption,required this.filterValue,required
this.isChecked});
@override
List<Object?> get props => [];
}
我在按下复选框时调用了那个事件
CheckBox( label: entry.key, onChanged: (isChecked) { context .read<LearningDashboardScreenBloc>() .add(CheckBoxValueChangedEvent(filterOption: widgetName, filterValue: entry.key, isChecked: isChecked)); }, key: GlobalKey<CheckBoxState>(), initValue: entry.value, ),
3.In bloc class 我编写了函数来更改状态 class 中的 bool 值并发出状态,
void _onCheckBoxValueChangedEvent(CheckBoxValueChangedEvent event,
Emitter<LearningDashboardScreenState> emit) {
Map<String, Map<String, dynamic>> filterOption = {};
filterOption=new Map<String, Map<String, dynamic>>.from(state.filterOption);
if (event.isChecked = true) {
filterOption[event.filterOption]![event.filterValue] = true;
} else {
filterOption[event.filterOption]![event.filterValue] = false;
}
emit(state.copyWith(filterOption: filterOption));
}
我的问题是当我勾选一个复选框时,
Error: Unhandled error Unsupported operation: Cannot modify unmodifiable map occurred in
Instance of 'LearningDashboardScreenBloc'.
问题是,当您将地图声明为 const
时,您无法修改地图。
在你的构造函数中 filterOption
有一个默认值 const
:
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
this.filterOption = const {
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {"Sinhala": false, "English": false, "Tamil": false},
"Duration": {"6 Months": false, "8 Months": false, "1Year": false},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
},
},
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED}
);
一个可能的解决方法是在初始化列表中定义映射文字,而不是作为默认参数(这样它就不需要是常量)。
LearningDashboardScreenState(
{this.courses = const [],
this.initialCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED,
Map<String, Map<String, dynamic>>? filterOption,
this.currPage = 0,
this.hasNextPage = false,
this.moreCoursesStatus = DataRetrievalStatus.NOT_INITIALIZED}
): this.filterOption = filterOption ??
{
"Certificate Provider": {"NVQ": false, "City and Guilds": false},
"Course Language": {
"Sinhala": false,
"English": false,
"Tamil": false
},
"Duration": {
"6 Months": false,
"8 Months": false,
"1Year": false
},
"Category": {
"Baby Care": false,
"First Aid": false,
"Adult Care": false,
"Mental Care": false,
"Physiotherapy": false,
"Baby First Aid": false,
"Light Housekeeping": false,
"Assist Methods": false
}
};