美文网首页
Flutter编译时生成代码之 code_builder

Flutter编译时生成代码之 code_builder

作者: brock | 来源:发表于2021-03-31 23:29 被阅读0次

    前言

    之前学习原生开发的时候使用过各种编译自动生成模板代码的框架,例如ARouter,这些框架其实是借助了JavaPoet 这个框架来自动生成代码的,JavaPoet 可以在编译自动生成模板代码,在flutter,也有这样的框架可以在编译时自动生成代码,这个框架就是 code_builder

    代码

    code_builder内部提供了一系列的api给开发人员使用,凭借这些api,我们可以创建任何代码。假如我们现在需要创建一个User类,代码如下:

    class User {
      User.User([this._name, this._age, this._sex]);
    
      String _name;
    
      int _age;
    
      int _sex;
    
      String get name => _name;
      int get age => _age;
      get sex => _sex;
      set name(String value) {
        _name = value;
      }
    
      set age(int value) {
        _age = value;
      }
    
      set sex(int value) {
        _sex = value;
      }
    
      @override
      String toString() {
        return "name = $_name; sex = $_sex; age = $_age";
      }
    }
    

    那我们该如何调用code_builder提供的api去创建这样一个类呢?可以这么做,如下代码所示:

    void getUser() {
      final user = Class((classBuild) => classBuild//生成一个类
        ..name = "User"//这个类的名字叫User
        ..fields.add(Field((fieldBuild) => fieldBuild//添加成员变量
          ..name = "_name"//该变量为私有变量,变量名为_name
          ..type = refer("String")//变量类型为String
        ))
        ..fields.add(Field((fieldBuild) => fieldBuild
          ..name = "_age"
          ..type = refer("int")
        ))
        ..fields.add(Field((fieldBuild) => fieldBuild
          ..name = "_sex"
          ..type = refer("int")
        ))
        ..constructors.add(Constructor((constructorBuilder){//添加构造函数
          constructorBuilder.name = "User";//构造函数的名字为User
          constructorBuilder.optionalParameters.add(Parameter((parameterBuilder) {//给构造函数添加一个参数
            parameterBuilder.name = "_name";// 给构造函数添加一个参数_name
            parameterBuilder.toThis = true;// 将参数_name赋值给成员变量_name
           }));
          constructorBuilder.optionalParameters.add(Parameter((parameterBuilder) {
            parameterBuilder.name = "_age";
            parameterBuilder.toThis = true;
          }));
          constructorBuilder.optionalParameters.add(Parameter((parameterBuilder) {
            parameterBuilder.name = "_sex";
            parameterBuilder.toThis = true;
          }));
        }))
        ..methods.add(Method((methodBuild) {// 创建一个方法
          methodBuild.type = MethodType.getter;// 方法是get类型的方法
          methodBuild.name = "name";// 方法名是name
          methodBuild.returns = refer("String");//方法返回类型是String
          methodBuild.lambda = true;// 方法是一个lambda表达式
          methodBuild.body = const Code("_name");// 创建方法体内的代码
        }))
        ..methods.add(Method((methodBuild){
          methodBuild.type = MethodType.getter;
          methodBuild.name = "age";
          methodBuild.returns = refer("int");
          methodBuild.lambda = true;
          methodBuild.body = const Code("_age");
        }))
        ..methods.add(Method((methodBuild){
          methodBuild.type = MethodType.getter;
          methodBuild.name = "sex";
          methodBuild.lambda = true;
          methodBuild.body = const Code("_sex");
        }))
        ..methods.add(Method((methodBuild) { //创建一个方法
          methodBuild.type = MethodType.setter; // 方法是set类型的方法
          methodBuild.name = "name";  // 方法名是name
          methodBuild.lambda = false; // 不是lambda表达式
          methodBuild.requiredParameters.add(Parameter((parameterBuild) { // 给方法添加参数
            parameterBuild.name = "value"; // 参数名是value
            parameterBuild.type = refer("String"); // 参数类似是String
          }));
          methodBuild.body = const Code("_name = value;"); // 方法体,对_name赋值为value
        }))
        ..methods.add(Method((methodBuild){
          methodBuild.type = MethodType.setter;
          methodBuild.name = "age";
          methodBuild.lambda = false;
          methodBuild.requiredParameters.add(Parameter((parameterBuild){
            parameterBuild.name = "value";
            parameterBuild.type = refer("int");
          }));
          methodBuild.body = const Code("_age = value;");
        }))
        ..methods.add(Method((methodBuild){
          methodBuild.type = MethodType.setter;
          methodBuild.name = "sex";
          methodBuild.lambda = false;
          methodBuild.requiredParameters.add(Parameter((parameterBuild){
            parameterBuild.name = "value";
            parameterBuild.type = refer("int");
          }));
          methodBuild.body = const Code("_sex = value;");
        }))
        ..methods.add(Method((methodBuild) {
          methodBuild.name = "toString";
          methodBuild.lambda = false;
          methodBuild.returns = refer("String");
          methodBuild.annotations.add(TypeReference((build) {// 给方法添加注解
            build.symbol = "override";//注解类型是@override,表示这是一个重写的方法
          }));
          methodBuild.body = const Code("return \"name = \$_name; sex = \$_sex; age = \$_age\"; ");
        }))
      );
      final emitter = DartEmitter();
      print(DartFormatter().format('${user.accept(emitter)}'));
    }
    
    void main() {
      getUser();
    }
    

    当然,光靠code_builder是不足以生成可以在实际项目中可以使用的类的,因为它只是创建了代码模板而已,我们还需要将这些代码模板写入到工程目录的某一个dart文件中,这个就需要借助source_gen了,source_gen可以在编译时解析注解,然后借助code_builder生成代码模板,最终将这些代码模板写入到工程目录的某一个dart文件中。

    QQ交流群

    群号码:770892444

    相关文章

      网友评论

          本文标题:Flutter编译时生成代码之 code_builder

          本文链接:https://www.haomeiwen.com/subject/xkdzhltx.html