Flutter Widget 之freezed

1,448 阅读2分钟

如果您由其他语言接触到以Dart语法表达的Flutter,您可能会注意到Dart语法 需要为简单的类编写许多样板代码

有时,您需要一个在构造函数中接受分配值的类,来提供有用的toString()覆盖,实现值相等性以及copyWith方法,因此对象可以保持不可变等诸如此类的功能

class MyClass {
    const MyClass({
        required int id,
        required bool isImportant,
    });
    
    final int id;
    final bool isImportant;
    
    @override
    String toString() => 'MyClass(id: $id, isImportant: $isImportant)';
    
    @override
    bool operator ==(dynamic other) {
        return identical(this, other) || 
            other.runtimeType == runtimeType &&
            other is MyClass &&
            identical(other.id, id) || other.id == id &&
            identical(other.isImportant, isImportant) || other.isImportant == isImportant;
    }
    
    MyClass copyWith({int? id, bool? isImportant}) =>
        MyClass(
            id: id ?? this.id,
            bool: isImportant ?? this.isImportant,
        );
}

但骤然间,类涵盖了这些基本功能就不再简单了。好在有像Freezed这样的代码生成包,让您无须编写数百行容易出错的样板代码

要使用Freezed,请将其作为dev_dependency添加到pubspec.yaml文件中,并新增普通依赖项freezed_annotation

dependencies:
    freezed_annotation: any
    
dev_dependencies:
    build_runner: any,
    freezed: any
    json_serializable: any

如果想用toJson()和fromJson()方法,还需要build_runner来作为dev_dependency和json_serializable,这样便一起就绪了

先用@Freezed()注释来装饰一个类,然后,指定将其纳入的超类

若Linter检查机制无法判读也无妨,Freezed随即就会生成相应代码

接下来从构造函数开始,使用const factory构造函数并将其指向同名并带有下划线前缀的类

同样,这个类还未生成,所以不用太在意Linter的检查结果

接着在此构造函数中指定数据类所需字段,

⚠️请注意,此处不使用正常的this.field name语法,因为这部分将交给Freezed生成

使用@Default装饰器来分配默认值

一旦所有字段都定义过了,加个FromJson构造函数,指示Freezed所需toJson和fromJson方法

这同样指向一个尚未生成的类

返回文件顶部加上这两个part的声明,方便Dart将此三个文件视为一个大文件

part 'my_class.freezed.dart';
part 'my_class.g.dart';

@Freezed()
class MyClass with _$MyClass{
    const factory MyClass({
        required int id,
        @Default(true) bool isImportant,
    }) = _MyClass;
    
    factory MyClass.fromJson(Map<String, dynamic> json) => _$MyClassFromJson(json);
}

最后来运行神奇的build_runner命令,以实际生成所缺的部分,大功告成

ezgif.com-gif-maker.gif

$ flutter pub run build_runner build --delete-conflicting-outputs

Freezed替您自动生成了单调的样板代码所含的一堆变数,让您能够做应用程序里您感兴趣的部分,

如果将来您需要添加更多的字段,可以把它们作为第一个构造函数的参数,重新运行build命令方才能做您感兴趣的事情

const factory MyClass({
    required int id,
    @Default(true) bool isImportant,
    int age
});

您可以用Freezed做很多事情, 所以一定要考虑它如何使您的代码更容易维护

image.png

如果想了解有关freezed 的内容,或者关于Flutter的其他功能,请访问flutter.dev

原文翻译自视频:视频地址