为了账号安全,请及时绑定邮箱和手机立即绑定

完美Model之AutoValue使用

标签:
Android

引言

之前看北京GDG直播收获颇丰,我打算用Github API来实践一下Piasy提出的完美model,这是这个系列的第一篇,时下非常流行apt生成代码,大家喜闻乐见的ButterKnife就是一个典型的例子,Google出品的AutoValue也是其中的翘楚,希望能通过这篇文章让你了解AutoValue。

github

在这个小项目中我将实践这个系列文章的所有技术,正在持续更新。
https://github.com/Bigmercu/PerfectModel
欢迎star fork issue

AutoValue

引用一段话来说明它的作用

“AutoValue is a great tool for eliminating the drudgery of writing mundane value classes in Java. It encapsulates much of the advice in Effective Java Chapter 2, and frees you to concentrate on the more interesting aspects of your program. The resulting program is likely to be shorter, clearer, and freer of bugs. Two thumbs up.”
– Joshua Bloch, author, Effective Java

这个大哥是Effective Java的作者,大大的有名啊,这段话大概说的是 AutoValue是一个非常棒的工具,它可以减少在Java里写很多重复的代码。这让你可以专注于程序中有趣的部分,它可以让你的代码更简短清晰,几乎没有bug。

less code其实是很有意义的,写的代码越少,自然出现bug的几率就越少。而AutoValue使用apt的方式来自动生成的代码没有bug,可以减少大量重复的工作,其实我们之前就在这么做了,比如IDE就自带了 getter 和 setter 生成等等。

那么它到底能做什么呢?

AutoValue可以用来生成实体。
一个我们熟悉的Entry可能包括哪些部分?

o    Field

o    getter()

o    setter()

o    equals()

o    hashCode()

o    null检查

o    toString()

o    构造方法

它还支持不限于

o    Gson解析支持->[auto-value-gson]

o    Parcelable支持->[auto-value-parcel]

o    简化和数据库交互->[sqldelight]

这些它都能做到(或者通过附加插件),并且大部分代码都不需要你手写了,想想就很美好啊TT。

怎么编写一个entry

首先 build.gradle script中插入:

1
2
3
4
dependencies {
  compileOnly "com.google.auto.value:auto-value:1.2"
  apt         "com.google.auto.value:auto-value:1.2"
}

o    用@AutoValue修饰类

o    将类加上修饰abstract

o    使用这样的形式来加入元素

1
2
abstract String name();
abstract int numberOfLegs();


rebuild一下,一个基本的实体就成了。
它默认包括:


o    getter()

o    setter()

o    equals()

o    hashCode()

o    null检查

o    toString()

o    构造方法

小tip

我们一般都会使用GsonFormater来格式化JSON数据,完事以后要修改成上面的形式可以有个小技巧。
首先修改前面的publicabstract
我只知道MAC的快捷键,Windows的同学自己发掘一下。

o    首先按住super键,把数遍放在public之前往下拖,就会得到多个光标,都在public之前
                                             
再往右拖,就能选中多个public了

o    键入abstract完成第一步,完事以后要在变量名后面加上括号,可以这么做:
按住super往右下角拖,选中所有要修改的行,并且保证光标在冒号后面
按一下方向右键,会退出选中状态,光标仍然在最后,再按一下左,光标来到每个变量名后面,这时键入()就可以了。
按一下ESC可以退出多行编辑

注意事项

o    在auto修饰的实体里,不要写包括但不限于 equals()/hashcode()/tostring() 等等方法,因为都会自动生成了。

o    要注意,如果元素可以为null,要使用@Nullable修饰,因为Autovalue会默认为所有没有@Nullable修饰的元素都生成null判断,一旦是null就会抛出NullPointerException(我被坑了这里)。

o    仍然可以使用@SerializedName()

o    如果有嵌套的类,也都一并要用 abstract修饰

最后的样子大概就是这样

其中的TypeAdapter后面会说。

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
31
32
33
34
35
36
37
38
@AutoValue
public abstract class SearchEntry {
   @SerializedName("total_count") abstract int total_count();
   @SerializedName("incomplete_results") abstract boolean incomplete_results();
    abstract String name();
    abstract int id();
    abstract List<ItemsBean> items();
    @AutoValue
    public abstract static class ItemsBean {
        abstract int id();
        abstract String name();
        @Nullable abstract String full_name();
        abstract OwnerBean owner();
        @SerializedName("private")
        abstract boolean privateX();
       ...
        @AutoValue
        public abstract static class OwnerBean {
            abstract String login();
            abstract int id();
            @Nullable  abstract String avatar_url();
        ...
            @Nullable  abstract String type();
            abstract boolean site_admin();
            public static TypeAdapter<OwnerBean> typeAdapter(Gson gson) {
                return new AutoValue_SearchEntry_ItemsBean_OwnerBean.GsonTypeAdapter(gson);
            }
        }
        public static TypeAdapter<ItemsBean> typeAdapter(Gson gson) {
            return new AutoValue_SearchEntry_ItemsBean.GsonTypeAdapter(gson);
        }
    }
    public static TypeAdapter<SearchEntry> typeAdapter(Gson gson) {
        return new AutoValue_SearchEntry.GsonTypeAdapter(gson);
    }
}

加入Builder支持

没用过Builder的同学可能会有点疑问,Builder可以干啥,看代码

1
2
3
4
Animal dog = Animal.builder()
     .setName("dog")
     .setNumberOfLegs(4)
     .build();

类似这样,可以创建一个对象。
Cook 步骤:

o    编写builder()方法,返回new AutoValue_*.Builder();具体根据你的实体名字修改

o    编写Builder类:

o    使用@AutoValue.Builder注解abstract static class Builder

o    在类中必须要有一个方法abstract T build(); 将T改为你的实体。

o    在类中用abstract Builder 变量名(变量类型 value) 这样的形式声明你所有的参数。

最后类似下面:

1
2
3
4
5
6
7
8
9
10
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();
 }

当然用法不仅于此,更多高级用法可以参考这篇Builder文档

auto-value-gson

这个AutoValue插件是用来生成GsonTypeAdapterFactory的,和大家熟知的Gson create方法不太一样,使用这个插件以后就可以这么实例化:

1
Gson mGson = new GsonBuilder().registerTypeAdapterFactory(MyAdapterFactory.create()).create();

在entry中加入typeAdapter方法

上面已经贴了代码了,一般形式

1
2
3
public static TypeAdapter<T> typeAdapter(Gson gson) {
       return new AutoValue_T.GsonTypeAdapter(gson);
   }

T 就是类名了,如果有内部嵌套的类,每个类都要写!
如果在这个过程中有错误提示之类的不要管,把代码敲上去以后rebuild一下就好了。

这样我们就能获得每个类的typeAdapter了,再创建一个方法来返回TypeAdapterFactory

1
2
3
4
5
6
@GsonTypeAdapterFactory
public abstract class MyAdapterFactory implements TypeAdapterFactory {
    public static TypeAdapterFactory create() {
        return new AutoValueGson_MyAdapterFactory();
    }
}

AutoValueGson_MyAdapterFactory中都做了啥?
就是根据类来返回对应的typeadapter,看到类似AutoValueGson_这样的类都是Autovalue生成的,不用我们写了。

得到TypeAdapterFactory以后我们就可以创建Gson对象了,有了Gson对象就可以解析JSON了。

1
2
SearchEntry mSearchEntry;
mSearchEntry = mGson.fromJson(str.toString(), SearchEntry.class);

AutoValue的强大之处不仅于此,序列化也有序列化插件auto-value-parcel,这个比较简单,有需要自己看看官方文档咯.

原文链接:http://www.apkbus.com/blog-705730-62500.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消