可选参数的默认值必须是常量

Oma*_*ajj 1 constants list optional-parameters dart flutter

所以我正在创建这个事件跟踪应用程序,我有两个屏幕,即地图和事件列表。我试图让地点列表等于我在应用程序状态中的地点。请记住,placeList 是一个可修改的列表,我需要将地点添加到此列表中。

但是,每当我初始化时,我都会收到“可选参数的默认值必须是常量”,this.places=PlaceMapState.placeList并且我无法将其更改为常量,因为我需要它来更新 PlaceMapState 类中的地点列表,并且我无法将其从 AppState 中删除,因为我在 PlaceList 类中使用它来获取地点列表。

我也不想完全删除 AppState,因为它还包含地图。

请问这个有什么解决办法吗???

这是我使用此列表的课程:

class AppState {
   AppState({
    this.places = PlaceMapState.placeList,           //// here is the problem!!!!!!!!!!!!!!!!!!!
    this.selectedCategory = PlaceCategory.events,
    this.viewType = PlaceTrackerViewType.map,
   }) : //assert(places != null),
        assert(selectedCategory != null);

   List<Place> places;
   PlaceCategory selectedCategory;
   PlaceTrackerViewType viewType;

  AppState copyWith({
    List<Place> places,
    PlaceCategory selectedCategory,
    PlaceTrackerViewType viewType,
  }) {
    return AppState(

      selectedCategory: selectedCategory ?? this.selectedCategory,
      viewType: viewType ?? this.viewType,
    );
  }

  static AppState of(BuildContext context) => AppModel.of<AppState>(context);

  static void update(BuildContext context, AppState newState) {
    AppModel.update<AppState>(context, newState);
  }

  static void updateWith(
    BuildContext context, {
    List<Place> places,
    PlaceCategory selectedCategory,
    PlaceTrackerViewType viewType,
  }) {
    update(
      context,
      AppState.of(context).copyWith(
        places: places,
        selectedCategory: selectedCategory,
        viewType: viewType,
      ),
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    if (other.runtimeType != runtimeType) return false;
    return other is AppState &&
        other.places == places &&
        other.selectedCategory == selectedCategory &&
        other.viewType == viewType;
  }

  @override
  int get hashCode => hashValues(places, selectedCategory, viewType);
}
Run Code Online (Sandbox Code Playgroud)

这是 placeList 类,我在其中使用地方来获取列表:

class PlaceList extends StatefulWidget {
  const PlaceList({Key key}) : super(key: key);

  @override
  PlaceListState createState() => PlaceListState();
}

class PlaceListState extends State<PlaceList> {
  ScrollController _scrollController = ScrollController();

  void _onCategoryChanged(PlaceCategory newCategory) {
    _scrollController.jumpTo(0.0);
    AppState.updateWith(context, selectedCategory: newCategory);
  }

  void _onPlaceChanged(Place value) {
    // Replace the place with the modified version.
    final newPlaces = List<Place>.from(AppState.of(context).places);
    final index = newPlaces.indexWhere((place) => place.id == value.id);
    newPlaces[index] = value;

    AppState.updateWith(context, places: newPlaces);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        _ListCategoryButtonBar(
          selectedCategory: AppState.of(context).selectedCategory,
          onCategoryChanged: (value) => _onCategoryChanged(value),
        ),
        Expanded(
          child: ListView(
            padding: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0),
            controller: _scrollController,
            shrinkWrap: true,
            children: AppState.of(context)
                .places                  //this the places im talking about!!!!!!!!!!!!!!!!!
                .where((place) =>
                    place.category == AppState.of(context).selectedCategory)
                .map((place) => _PlaceListTile(
                      place: place,
                      onPlaceChanged: (value) => _onPlaceChanged(value),
                    ))
                .toList(),
          ),
        ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

jam*_*lin 9

Dart 要求可选参数的默认参数是编译时常量。如果没有这个要求,那么给出如下:

List<int> f(List<int> list = <int>[]) {
  list.add(42);
  return list;
}
Run Code Online (Sandbox Code Playgroud)

会有一个问题,f();重复调用是否应该:

  • List每次创建一个新的,这对于任意对象可能效率低下。
  • 使用相同的默认List实例,这意味着相同的实例将被重复变异并返回。

如果您无法设置默认参数const,则常见的解决方法是将默认值设置为可以哨兵值。通常,哨兵参数可以是,这要求您的参数可以为空。(初始化成员变量时,成员变量本身可以保持不可为空。)例如:constnull

class AppState {
  AppState({
    List<Place>? places,
    ...
  }) : places = places ?? PlaceMapState.placeList;

  List<Place> places;

  ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您的成员和参数已经可以为空,则使用null此方法显式传递作为参数将执行与直接设置默认值不同的操作。即对比:

class Foo {
  int? value;

  Foo(this.value = 0);
}
Run Code Online (Sandbox Code Playgroud)

到:

class Bar {
  int? value;

  Bar(int? value) : value = value ?? 0;
}
Run Code Online (Sandbox Code Playgroud)

Foo()并且会做不同的事情,而和Foo(null)之间没有区别(尽管在某些情况下这是可取的)。Bar()Bar(null)