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 => [];
  }
  1. 我在按下复选框时调用了那个事件

                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
              }
            };