如何在Flutter Dart的freezed模型中使用late final关键字?

huangapple go评论86阅读模式
英文:

How to use late final keyword in Flutter Dart freezed model?

问题

在Flutter Dart的freezed模型中如何使用late final关键字?

这段代码生成成功,没有静态分析错误,但奇怪的是它无法编译。

import 'dart:convert';

import 'package:freezed_annotation/freezed_annotation.dart';

part 'fb_story.freezed.dart';
part 'fb_story.g.dart';

@freezed
class FbStory with _$FbStory {
  FbStory._();
  const factory FbStory({
    required String id,
    required String data_str,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;

  late final Map<String, dynamic> data = jsonDecode(data_str);

  factory FbStory.fromJson(Map<String, dynamic> json) =>
      _$FbStoryFromJson(json);
}

错误:

Error: A constant constructor can't call a non-constant super constructor.

在以前,Freezed使用@late注解来引入late关键字,所以我猜应该有一种方法可以使这个工作。该类仍然被freezed修饰,只是变成了懒加载。

英文:

How to use late final keyword in Flutter Dart freezed model ?

This code generates successfully and has no static analysis error but it does not compile strangely.

import &#39;dart:convert&#39;;

import &#39;package:freezed_annotation/freezed_annotation.dart&#39;;

part &#39;fb_story.freezed.dart&#39;;
part &#39;fb_story.g.dart&#39;;

@freezed
class FbStory with _$FbStory {
  FbStory._();
  const factory FbStory({
    required String id,
    required String data_str,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;

  late final Map&lt;String, dynamic&gt; data = jsonDecode(data_str);

  factory FbStory.fromJson(Map&lt;String, dynamic&gt; json) =&gt;
      _$FbStoryFromJson(json);
}

Error:

 Error: A constant constructor can&#39;t call a non-constant super constructor.

Before, Freezed used to pioneer the late keyword with @late annotation so I guess there should be a way to make this work. class is still freezed, just lazy

答案1

得分: 1

错误非常明确,您不能在带有late变量的情况下拥有const构造函数。这不是freezed的错误,普通的Dart类也会出现这个错误:

class FbStory {
  const FbStory(this.data_str);
  
  final String data_str;
  
  // 无法定义'const'构造函数,因为字段'data'被初始化为非常量值。
  late final Map<String, dynamic> data = jsonDecode(data_str);
}

要解决此问题,我建议从const factory FbStory(...)中删除const

或者,您可以创建一个由json_serializable提供的转换器类:

class StringToMapConverter implements JsonConverter<Map<String, dynamic>, String> {
  const StringToMapConverter();

  @override
  Map<String, dynamic> fromJson(String json) {
    return jsonDecode(json) as Map<String, dynamic>;
  }

  @override
  String toJson(Map<String, dynamic> object) {
    return jsonEncode(object);
  }
}

然后,您的类FbStory将如下所示:

@freezed
class FbStory with _$FbStory {
  FbStory._();
  const factory FbStory({
    required String id,
    @JsonKey(name: 'data_str')
    @StringToMapConverter()
    required Map<String, dynamic> data,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;
英文:

The error is quite explicit, you cannot have a const constructor with a late variable. This is not an error with freezed, a normal Dart class will also have this error:

class FbStory {
  const FbStory(this.data_str);
  
  final String data_str;
  
  // Can&#39;t define the &#39;const&#39; constructor because the field &#39;data&#39;
  // is initialized with a non-constant value.
  late final Map&lt;String, dynamic&gt; data = jsonDecode(data_str);
}

To fix your issue I would recommend to remove the const from your const factory FbStory(...).

Or you could create a converter class provided by json_serializable:

class StringToMapConverter implements JsonConverter&lt;Map&lt;String, dynamic&gt;, String&gt; {
  const StringToMapConverter();

  @override
  Map&lt;String, dynamic&gt; fromJson(String json) {
    return jsonDecode(json) as Map&lt;String, dynamic&gt;;
  }

  @override
  String toJson(Map&lt;String, dynamic&gt; object) {
    return jsonEncode(object);
  }
}

Your class FbStory would then look like this:

@freezed
class FbStory with _$FbStory {
  FbStory._();
  const factory FbStory({
    required String id,
    @JsonKey(name: &#39;data_str&#39;)
    @StringToMapConverter()
    required Map&lt;String, dynamic&gt; data,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;

答案2

得分: -1

只需在factory FbStory上删除const

完整代码:

import 'dart:convert';

import 'package:freezed_annotation/freezed_annotation.dart';

part 'fb_story.freezed.dart';
part 'fb_story.g.dart';

@freezed
class FbStory with _$FbStory {
  FbStory._();
  factory FbStory({
    required String id,
    required String data_str,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;

  late final Map<String, dynamic> data = jsonDecode(data_str);

  factory FbStory.fromJson(Map<String, dynamic> json) =>
      _$FbStoryFromJson(json);
}
英文:

Just remove const at factory FbStory

Full code:

import &#39;dart:convert&#39;;

import &#39;package:freezed_annotation/freezed_annotation.dart&#39;;

part &#39;fb_story.freezed.dart&#39;;
part &#39;fb_story.g.dart&#39;;



@freezed
class FbStory with _$FbStory {
  FbStory._();
  factory FbStory({
    required String id,
    required String data_str,
    @Default(false) bool imageNotAvailable,
    @Default(false) bool videoNotAvailable,
    String? imageUrl,
    String? videoUrl,
  }) = _FbStory;

  late final Map&lt;String, dynamic&gt; data = jsonDecode(data_str);

  factory FbStory.fromJson(Map&lt;String, dynamic&gt; json) =&gt;
      _$FbStoryFromJson(json);
}

huangapple
  • 本文由 发表于 2023年6月19日 05:47:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定