Android Model正确使用姿势——AutoValue
最近看到几篇博客是关于AutoValue的,然后自己十分喜欢,一下子觉的这样写代码很优雅,所以决定自己也写一篇文章介绍下AutoValue。
本文最先发表于Github,如有转载,请注明转载出处。
前言
首先说Android Model,在开发中网络请求,以及数据库操作等,我们都会定义一个Model,不同人对这个的说法不一样,比如有Entry,Bean,Pojo。
然后开发的过程中会遇到下面问题:
构成方法:自定义构造方法,如果实体比较复杂,可能会用到工厂模式或者是建造者模式
序列化:比如实现Serializable接口,Parcelable接口。
Json解析:有时候直接使用的是json数据,比如@SerializedName注解。
自定义方法:对Model的字段有setter,getter方法,toString的实现,在处理hash的时候,需要实现equals和hashcode方法。
以上这么问题,其实在Eclipse和Android Studio中都是有快捷功能帮我们自动生成,后面的代码示例,就是我用Android Studio自动生成的。
比如下面一个User类是我们的本次示例的一个Model,如果按照正常的写法,是这样的。
public abstract class User implements Serializable {
@SerializedName("id")
private int id;
@SerializedName("name")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (id != user.id) return false;
return name != null ? name.equals(user.name) : user.name == null;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
简介
官方文档给出的解释是这样的,大致意思是说是一个生成Java不可变的值类型工具,仔细研读源代码后,使用的技术是Java Apt,这个后面再做详细解释。
AutoValue - Immutable value-type code generation for Java 1.6+.
简单使用
按照上面的例子,如果是AutoValue,代码是这样的。
首先需要在Android项目里面引入apt功能,在项目根目录的gradle中添加,
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
// 引入apt插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
其次在module(一般是app目录)中gradle使用apt插件。
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
最后加入AutoValue依赖。
dependencies {
provided 'com.google.auto.value:auto-value:1.3'
apt 'com.google.auto.value:auto-value:1.3'
}
修改User类,如下所示,User已经变成了一个抽象类,类似于使用Retrofit一样,申明已经变成了一个接口,然后实现类是由AutoValue生成的代码。
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class User {
public abstract int id();
public abstract String name();
public static User newInstance(int id, String name) {
return new AutoValue_User(id, name);
}
}
我们可以看看AutoValue到底干了什么?
AutoValue会自动生成一个AutoValue_User,这个类是继承了上面申明的User类,这个是默认default的访问权限,那么在其他package中是无法访问的,这样在其他代码里面也不会看到这么奇怪的名字。
同时所有的字段都是final类型,如果字段是对象类型的,那么还不能为空,这个问题先保留,后面再做详解。因为申明的是final类型,那么所有的字段都是没有setter方法的。
代码里同时也实现了equals、hashcode、toString方法。
final class AutoValue_User extends User {
private final int id;
private final String name;
AutoValue_User(
int id,
String name) {
this.id = id;
if (name == null) {
throw new NullPointerException("Null name");
}
this.name = name;
}
@Override
public int id() {
return id;
}
@Override
public String name() {
return name;
}
@Override
public String toString() {
return "User{"
+ "id=" + id + ", "
+ "name=" + name
+ "}";
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof User) {
User that = (User) o;
return (this.id == that.id())
&& (this.name.equals(that.name()));
}
return false;
}
@Override
public int hashCode() {