AutoValue 探究(二)

本文继续对 AutoValue 的使用方法进行深入介绍。 前置文章:AutoValue 探究(一)

默认情况下,AutoValue 生成的类中域是非空的,如果要使得域可以为空,则需要使用 @Nullable 注解,如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import android.support.annotation.Nullable;

import com.google.auto.value.AutoValue;
import com.google.gson.annotations.SerializedName;

@AutoValue
public abstract class User {

    @SerializedName("id")
    public abstract int id();

    @Nullable
    @SerializedName("name")
    public abstract String name();
}

生成的代码为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
final class AutoValue_User extends User {

    private final int id;
    private final String name;

    AutoValue_User(
      int id,
      @Nullable String name) {
        this.id = id;
        this.name = name;
    }
}

AutoValue 与 Gson 搭配使用时,要额外做一些处理工作。 首先,需要引入 AutoValue Gson 插件,即在 Gradle 文件中加入如下依赖描述:

1
2
annotationProcessor 'com.ryanharter.auto.value:auto-value-gson:0.5.0'
provided 'com.ryanharter.auto.value:auto-value-gson:0.5.0'

其次,申明的抽象类中,每个方法上面添加对应的注解,然后再添加一个 typeAdapter 方法,申明这个方法,Gson 就会根据这个找到对应的 adapter,如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@AutoValue
public abstract class User {

    @SerializedName("id")
    public abstract int id();

    @SerializedName("name")
    public abstract String name();

    public static User newInstance(int id, String name) {
        return new AutoValue_User(id, name);
    }

    public static TypeAdapter<User> typeAdapter(Gson gson) {
        return new AutoValue_User.GsonTypeAdapter(gson);
    }
}

再次,声明一个 TypeAdapterFactory 的实现类,这个类应是抽象类,AutoValue 也会自动生成其实现类,比如:

1
2
3
4
5
6
7
@GsonTypeAdapterFactory
public abstract class MyAdapterFactory implements TypeAdapterFactory {

    public static TypeAdapterFactory create() {
        return new AutoValueGson_MyAdapterFactory();
    }
}

最后,在 json 字符串转值类的时候,需要自用到上面所申明的 MyAdapterFactory,比如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Test
    public void testUserToJson() {
        User user = User.newInstance(100, "test");

        String json = new Gson().toJson(user);
        System.out.println(json);

        Assert.assertEquals("{\"id\":100,\"name\":\"test\"}", json);
    }

    @Test
    public void testUserParseFromJson() {
        String json = "{\"id\":100,\"name\":\"test\"}";
        
        // 自定义的Gson对象,需要配置 MyAdapterFactory
        Gson gson = new GsonBuilder().registerTypeAdapterFactory(MyAdapterFactory.create()).create();

        User user = gson.fromJson(json, User.class);
        System.out.println(user);
        Assert.assertNotNull(user);
        Assert.assertEquals(user.name(), "test");
        Assert.assertEquals(user.id(), 100);

        NullableUser nullableUser = gson.fromJson(json, NullableUser.class);
        System.out.println(nullableUser);
        Assert.assertNotNull(nullableUser);
        Assert.assertEquals(nullableUser.name(), "test");
        Assert.assertEquals(nullableUser.id(), 100);
    }

Serializable 是 Java 自带的序列化方式,和 AutoValue 结合不影响原先使用,只需要在申明的 Model 中实现 Serializable 接口即可。

Parcelable 是 Android 提供的序列化方式,如果需要和 AutoValue 结合使用,和 Serializable 基本差不多,实现相关接口,添加相关插件 AutoValue Parcel 即可:

1
2
3
4
annotationProcessor 'com.ryanharter.auto.value:auto-value-parcel:0.2.5'

// Optionally for TypeAdapter support
compile 'com.ryanharter.auto.value:auto-value-parcel-adapter:0.2.5'

结果自动生成的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
final class AutoValue_User extends $AutoValue_User {
    public static final Parcelable.Creator<AutoValue_User> CREATOR = new Parcelable.Creator<AutoValue_User>() {
    @Override
    public AutoValue_User createFromParcel(Parcel in) {
        return new AutoValue_User(
          in.readInt(),
          in.readString()
        );
    }
    @Override
    public AutoValue_User[] newArray(int size) {
        return new AutoValue_User[size];
    }
    };

    AutoValue_User(int id, String name) {
        super(id, name);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id());
        dest.writeString(name());
    }

    @Override
    public int describeContents() {
        return 0;
    }
}

Android Model正确使用姿势 —— AutoValue