文章

auto(Goodle AutoValue)

auto(Goodle AutoValue)

auto(Goodle AutoValue)

google AutoValue

Google AutoValue 一个 Java 不可变数据类型的代码生成库,用于帮我们生成 Bean 的 getter()hashCode()equals()toString(),注意没有 setter()
开源项目主页
https://github.com/google/auto
官网文档:
https://github.com/google/auto/blob/master/value/userguide/index.md
Why use AutoValue?
https://github.com/google/auto/blob/master/value/userguide/why.md

生成的 immutable,没有 setter 方法,怎么修改?

简单用法

添加 dependencies
1
2
provided 'com.google.auto.value:auto-value:1.2'
apt 'com.google.auto.value:auto-value:1.2'
创建一个 abstract 类使用 @AutoValue 作用于类上
1
2
3
4
5
@AutoValue
public abstract class Story {
    public abstract int id();
    public abstract String title();
}

使用 @AutoValue 注解后,AutoValue 会生成一个 AutoValue_你的类名 为名称的类并继承你写的抽象类,这个类是 包级私有 的,他里面有私有的成员变量,对应的构造函数,以及重写的 hashCode()equals()toString() 方法。由于这个生成的子类是包级私有的,所以这里在给 Story 提供构造方法的时候需要提供一个静态的构造方法。

[生成 Builder 代码]
  • 编写 builder() 方法,返回 new AutoValue_*.Builder(); 具体根据你的实体名字修改
  • 编写 Builder 类:
    • 使用 @AutoValue.Builder 注解 abstract static class Builder
    • 在类中必须要有一个方法 abstract T build(); 将 T 改为你的实体。
    • 在类中用 abstract Builder 变量名(变量类型 value) 这样的形式声明你所有的参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@AutoValue
public abstract class Animal {
    abstract String name();
    abstract int numberOfLegs();
    static Builder builder() {
        return new AutoValue_Animal.Builder();
    }
    @AutoValue.Builder
    abstract static class Builder {
        abstract Builder name(String value);
        abstract Builder numberOfLegs(int value);
        abstract Animal build();
    }
}

使用

1
Animal animal = Animal.builder().name("dog").numberOfLegs(4).build();

注意

类必须是 abstract,并且只能是带有返回值的无参数的 abstract 的方法,返回值不能是 void,也不能带有参数。修饰符不能为 private
1
2
3
4
// 带有参数的
abstract String name(int age);
// 返回值为void的
abstract void haha();
equals()、hashCode()toString() 如果你想要实现你自己版本的这些方法(或其中之一),你可以在注解类中自己实现,AutoValue 会识别出来并不产生代码,你的实现也会被继承并在 final 类中被使用
生成的类
  • 生成类继承了添加注解的抽象类,生成的类是 final 的,而且带有 AutoValue_ 前缀。
  • 如果你想要在添加注解的类中访问生成的代码的话,这一点很重要。因为这样就像通过静态工厂方法访问构造器。
  • 该类是包间私有的。因此在其他包里无法看到生成的类,当然,它也不应该在其他类中被使用。
  • 该类构造器也是包间私有的,将所有参数作为属性
  • 构造器中对传入的参数作了判断,所有属性都不会是空。如果你想让某个属性为空,不妨添加一个 @Nullable 注解
1
2
3
4
@AutoValue
public abstract class User {
  @Nullable public abstract String middleName();
}
  • 成员变量真的没什么特别的,唯一要说的就是数据域都是 final,以保证类型不变性。

AutoValue Extension API

Reference

使用 Google AutoValue 自动生成代码
http://www.jianshu.com/p/0e2be3536a4e
深入研究 AutoValue
https://github.com/hehonghui/android-tech-frontier/blob/master/issue-49/深入研究AutoValue.md

auto-service

auto-service
https://github.com/google/auto/tree/master/service

使用

1
2
'com.google.auto.service:auto-service:1.0-rc2'
'com.squareup:javapoet:1.8.0'

在你的 Processor 上添加 @AutoService(Processor.class)

1
2
3
4
5
6
7
8
package foo.bar;

import javax.annotation.processing.Processor;

@AutoService(Processor.class)
final class MyProcessor extends Processor {
  // …
}

会在 src/main/ 生成 META-INF/services/javax.annotation.processing.Processor

1
me.hacket.BindViewProcessor
本文由作者按照 CC BY 4.0 进行授权