Frenda:一个专注于简化Dart实体生成的工具

692 阅读2分钟

在Flutter开发中,处理JSON序列化、对象拷贝等操作是很常见的需求。现有的方案各有特点,但在使用过程中也存在一些不便,这促使我开发了Frenda —— 一个致力于简化这些操作的代码生成工具。

现状分析

目前Flutter生态中比较常用的代码生成方案有:

  1. json_serializable

    • 优点:生成JSON序列化相关代码,使用广泛
    • 不足:需要额外编写copyWith等实用方法
  2. freezed

    • 优点:提供了较为完整的功能支持
    • 不足:
      • 需要额外依赖json_serializable
      • 生成的泛型类缺少统一的接口约束
      • 需要手动编写部分fromJson方法

Frenda的实现思路

Frenda的目标是通过简单的类定义自动生成必要的代码。让我们通过一个例子来说明:

import 'package:frenda/frenda.dart';

part 'simple.dart';

// 注解标注,类名必须以 $ 进行开头
@frenda
class $Simple {
  // 定义一个字段
  late String firstField;
  
  // 带默认值的final字段
  late final int secondField = 10;
  
  // 自定义JSON序列化时的字段名
  // 生成时会使用'third_field'作为JSON的key
  @Filed('third_field')
  late bool? thirdField;
}

运行代码生成后,Frenda会自动生成如下实现:

// 统一实现了Serializable接口
class Simple implements Serializable {
  String firstField;
  final int secondField;
  bool? thirdField;

  // 构造函数,required标记必填字段
  Simple({
    required this.firstField, 
    this.secondField = 10, 
    this.thirdField
  });

  // JSON序列化
  Map<String, dynamic> toJson() => {
    'firstField': firstField,
    'secondField': secondField,
    'third_field': thirdField, // 使用自定义的字段名
  };

  // JSON反序列化
  factory Simple.fromJson(Map<String, dynamic> json) => Simple(
    firstField: json['firstField'] as String,
    secondField: json['secondField'] as int,
    thirdField: json['third_field'] as bool?,
  );

  // 对象拷贝,保持不可变性
  Simple copyWith({String? firstField, int? secondField, bool? thirdField}) => 
      Simple(/*...*/);

  // 清晰的字符串表示
  @override
  String toString() => 'Simple(firstField: $firstField, /*...*/}';

  // 正确的相等性比较
  @override
  bool operator ==(Object other) => /*...*/;

  // 配套的hashCode实现
  @override
  int get hashCode => Object.hash(firstField, secondField, thirdField);
}

主要特点

  1. 注重简洁

    • 仅需类定义和必要的注解
    • 生成代码遵循Dart的最佳实践
  2. 保持灵活

    • 支持自定义JSON字段名
    • 支持可空类型和默认值
    • 实现统一的Serializable接口,便于泛型处理

配置方法

  1. 添加依赖:
dependencies:
  frenda: any

dev_dependencies:
  build_runner: any
  1. 可选的build配置:
targets:
  $default:
    builders:
      frenda:    
        options:
          prefix: "$"  # 类名前缀,默认为$

实现原理

Frenda基于Dart的代码生成体系构建,主要使用了:

  • build: 代码生成框架
  • source_gen: Dart代码生成工具
  • analyzer: Dart代码分析器

生成过程包括:

  1. 分析源类定义和注解信息
  2. 根据类信息生成相应的方法实现

使用建议

  1. 类名前缀(默认是$)保持统一,便于识别
  2. 建议给字段添加适当的注释,提高代码可读性
  3. 对于复杂的序列化逻辑,可以考虑自定义实现

结语

Frenda是一个实用的代码生成工具,它的目标是减少重复工作,帮助开发者专注于业务逻辑。

目前还在持续改进中,欢迎社区的朋友们试用并提出宝贵意见。

项目地址

如果项目对你有帮助,欢迎Star支持。有任何建议或问题,也欢迎通过Issue交流!