Android AutoValue使用和扩展库
一、什么是AutoValue
意思就是自动值,谷歌出品,添加@AutoValue
这样的注解 就能够自动生成代码,使得程序可能更短,更清晰。 支持Java1.6+
github:
https://github.com/google/auto/blob/master/value/userguide/index.md
首先看一个bean类,User.java:
public class User{private String name;private String addr;private int age;private String gender;private String hobby;private String sign;public String getName() {return name;}public void setName(String name) {this.name = name;}....(太多就省略了)
}
一堆的getter和setter代码很多,到时候添加toString
、hashCode
、equals
这些代码就更麻烦了(虽然ide有快速生成),这时候AutoValue就来拯救世界了。
二、基本使用
一步一脚印
2.1 导包
初次使用需要注意,官方只说了在module依赖,这样会build失败的,对于新手来说会一脸懵逼,因为需要apt。
项目的build.gradle添加依赖:
dependencies {//添加这行classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'}
在module的build.gradle依赖以下,当前最新是1.4.1
//顶部添加
apply plugin: 'com.neenbedankt.android-apt'dependencies {compile "com.google.auto.value:auto-value:1.4.1"apt "com.google.auto.value:auto-value:1.4.1"
}
重新Sync即可
2.2 使用AutoValue标识bean
现在来重新编写User类:
@AutoValue
public abstract class User {abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();}
然后build -> make module一下,这时候就会生成AutoValue_User.java
,在build\generated\source\apt\debug\包名\AutoValue_User.java
里面的代码为:
final class AutoValue_User extends User {private final String name;private final String addr;private final int age;private final String gender;private final String hobby;private final String sign;AutoValue_User(String name,String addr,int age,String gender,String hobby,String sign) {if (name == null) {throw new NullPointerException("Null name");}this.name = name;if (addr == null) {throw new NullPointerException("Null addr");}this.addr = addr;this.age = age;if (gender == null) {throw new NullPointerException("Null gender");}this.gender = gender;if (hobby == null) {throw new NullPointerException("Null hobby");}this.hobby = hobby;if (sign == null) {throw new NullPointerException("Null sign");}this.sign = sign;}@OverrideString name() {return name;}@OverrideString addr() {return addr;}@Overrideint age() {return age;}@OverrideString gender() {return gender;}@OverrideString hobby() {return hobby;}@OverrideString sign() {return sign;}@Overridepublic String toString() {return "User{"+ "name=" + name + ", "+ "addr=" + addr + ", "+ "age=" + age + ", "+ "gender=" + gender + ", "+ "hobby=" + hobby + ", "+ "sign=" + sign+ "}";}@Overridepublic boolean equals(Object o) {if (o == this) {return true;}if (o instanceof User) {User that = (User) o;return (this.name.equals(that.name()))&& (this.addr.equals(that.addr()))&& (this.age == that.age())&& (this.gender.equals(that.gender()))&& (this.hobby.equals(that.hobby()))&& (this.sign.equals(that.sign()));}return false;}@Overridepublic int hashCode() {int h = 1;h *= 1000003;h ^= this.name.hashCode();h *= 1000003;h ^= this.addr.hashCode();h *= 1000003;h ^= this.age;h *= 1000003;h ^= this.gender.hashCode();h *= 1000003;h ^= this.hobby.hashCode();h *= 1000003;h ^= this.sign.hashCode();return h;}}
这个类就是生成的类,里面就帮你编写好了各种方法hashCode
、toString
、equals
、getter
和setter
等等。
2.3 构造方法
这时候构造方法利用自己写的一个方法来实现newAutoValue_User
,在User类里面添加create方法进行调用生成的AutoValue_User
,这时候bean的方法这样的:
@AutoValue
public abstract class User {abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();//创建User,内部调用的是AutoValue_Userstatic User create(String name,String addr,int age,String gender,String hobby,String sign){return new AutoValue_User(name,addr,age,gender,hobby,sign);}}
2.4 使用
使用User.create方法即可创建对应User对象:
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);User user = User.create("天平","广东",21,"男","敲代码","没有个性签名");Log.e("@@", "onCreate: "+user.toString());}
}
即可看到输出
onCreate: User{name=天平, addr=广东, age=21, gender=男, hobby=敲代码, sign=没有个性签名}
三、扩展api
你以为AutoValue的功能就那么少吗 ? 错,他还有很多扩展api。
3.1 auto-value-parcel
当User需要实现Parcelable接口的时候,AutoValue也可以帮你搞定了。
在基本的使用基础上继续导包(当前最新是0.2.5):
github地址:https://github.com/rharter/auto-value-parcel
apt 'com.ryanharter.auto.value:auto-value-parcel:0.2.5'// 需要自定义TypeAdapter就要导入
compile 'com.ryanharter.auto.value:auto-value-parcel-adapter:0.2.5'
基本Parcelable
这时候把User实现接口即可:
@AutoValue
public abstract class User implements Parcelable{abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();static User create(String name,String addr,int age,String gender,String hobby,String sign){return new AutoValue_User(name,addr,age,gender,hobby,sign);}}
重新make一下moduel即可看到生成的AutoValue_User
继承的原来的$AutoValue_User
类,把Parcelable
需要实现的方法放在了AutoValue_User类:
final class AutoValue_User extends $AutoValue_User {public static final Parcelable.Creator<AutoValue_User> CREATOR = new Parcelable.Creator<AutoValue_User>() {@Overridepublic AutoValue_User createFromParcel(Parcel in) {return new AutoValue_User(in.readString(),in.readString(),in.readInt(),in.readString(),in.readString(),in.readString());}@Overridepublic AutoValue_User[] newArray(int size) {return new AutoValue_User[size];}};AutoValue_User(String name, String addr, int age, String gender, String hobby, String sign) {super(name, addr, age, gender, hobby, sign);}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name());dest.writeString(addr());dest.writeInt(age());dest.writeString(gender());dest.writeString(hobby());dest.writeString(sign());}@Overridepublic int describeContents() {return 0;}
}
其他类型Parcelable
Parcel 这个扩展支持Parcel类支持的所有类型,但有时您可能需要parcel其他类型,如SparseArray或ArrayMap。您可以使用自定义TypeAdapter执行此操作(需要导入auto-value-parcel-adapter)
例如User里面有一个类型Date。这时候需要为Date定义一个TypeAdapters:
public class DateTypeAdapter implements TypeAdapter<Date> {public Date fromParcel(Parcel in) {return new Date(in.readLong());}public void toParcel(Date value, Parcel dest) {dest.writeLong(value.getTime());}
}
然后User添加Date类型:
@AutoValue
public abstract class User implements Parcelable{abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();//需要注解自定义的TypeAdapter@ParcelAdapter(DateTypeAdapter.class)public abstract Date date();static User create(String name,String addr,int age,String gender,String hobby,String sign,Date date){return new AutoValue_User(name,addr,age,gender,hobby,sign,date);}}
这里为延迟数据传递,新建一个SecondActivity,在MainActivit传递user过去
MainActivity.java
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);User user = User.create("天平","广东",21,"男","敲代码","没有个性签名",new Date());startActivity(new Intent(this,SecondActivity.class).putExtra("bean",user));}
}
SecondActivity.java
public class SecondActivity extends Activity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);User user = getIntent().getParcelableExtra("bean");Log.e("@@two", "onCreate: "+user.toString());}
}
即可看到输出:
E/@@: onCreate: User{name=天平, addr=广东, age=21, gender=男, hobby=敲代码, sign=没有个性签名, date=Mon Mar 13 14:36:19 GMT+08:00 2017}
3.2 auto-value-gson
就是你的用了AutoValues来修饰定义了Bean对象,Gson的就不能按照平常的方式来解析了,需要改变一下。
普及知识:
Gson的TypeAapter可以理解成自定义序列化和返序列化。通过实现JsonSerializer和JsonDeserializer进行序列化和反序列化,在Gson创建的时候registerTypeAdapter(你的自定义TypeAapter)。 具体请百度。
auto-value-gson 的github地址: https://github.com/rharter/auto-value-gson
导包(当前最新是0.4.6,注意,使用需要Gson,就是也要有Gson的包存在)
apt 'com.ryanharter.auto.value:auto-value-gson:0.4.6'
provided 'com.ryanharter.auto.value:auto-value-gson:0.4.6'compile 'com.google.code.gson:gson:2.8.0'
3.2.1 在Bean类添加TypeAdapter
Gson解析AutoValue修饰的对象,
这时候User是这样的:
@AutoValue
public abstract class User implements Parcelable{abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();//需要注解自定义的TypeAdapter@ParcelAdapter(DateTypeAdapter.class)public abstract Date date();//添加一个TypeAdapter<User>,这个TypeAdapter是Gson包里面的。public static TypeAdapter<User> typeAdapter(Gson gson){// AutoValue_User.GsonTypeAdapter 需要先make一下module之后才会生成return new AutoValue_User.GsonTypeAdapter(gson).setDefaultAddr("默认地址"); //还可以设置默认值}}
注意: TypeAdapter,这个TypeAdapter是Gson包里面的。AutoValue_User.GsonTypeAdapter(gson) 需要先make一下module之后才会生成。
3.2.2 编写TypeAdapterFactory
然后编写对应的编写TypeAdapterFactory类,使用@GsonTypeAdapterFactory
注解去修饰。
@GsonTypeAdapterFactory
public abstract class UserAdapterFactory implements TypeAdapterFactory {// 静态工厂方式public static TypeAdapterFactory create() {return new AutoValueGson_UserAdapterFactory();}}
3.2.3 Gson解析
上面搞好了之后,尝试来解析json为User看看。
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//json字符串String json = "{\"name\":\"天平\",\"addr\":\"广东\",\"age\":21,\"gender\":\"男\",\"hobby\":\"打代码\",\"sign\":\"签名\",\"date\":\"2017-3-13 14:36:19\"}";//初始化GsonGson gson = new GsonBuilder().registerTypeAdapterFactory(UserAdapterFactory.create()) //注册自定义的TypeAdapterFactory.setDateFormat("yyyy-MM-dd HH:mm:ss") //设置json里面的Date格式.create();//开始解析User user = gson.fromJson(json,User.class);//输出结果Log.e("@@", "onCreate: "+user.toString());}
}
即可看到:
onCreate: User{name=天平, addr=广东, age=21, gender=男, hobby=打代码, sign=签名, date=Mon Mar 13 14:36:19 GMT+08:00 2017}
四、小细节
4.1 Gson泛型支持
如果你的bean类里面有泛型,这时候你的TypeAdapter也需要泛型,还要添加参数TypeToken,例如:
@AutoValue public abstract class Foo<A, B, C> {abstract A data();abstract List<B> dataList();abstract Map<String, List<C>> dataMap();public static <A, B, C> TypeAdapter<Foo<A, B, C>> typeAdapter(Gson gson,TypeToken<? extends Foo<A, B, C>> typeToken) {return new AutoValue_Foo.GsonTypeAdapter(gson, typeToken);}
}
4.2 可选配置
添加了下面的设置,maps/collections将默认为它们的空类型(例如List - > Collections.emptyList()) 值为true或false。
apt {arguments {autovaluegson.defaultCollectionsToEmpty 'true'}
}
4.3 AutoValue plugin插件
可以生成create Builder等代码,不过不能生成TypeAdapter代码:
插件仓库搜索: AutoValue plugin
开源地址: https://github.com/afcastano/AutoValuePlugin
使用方法: 安装插件重启了As之后,在Bean里面Alt+回车 即可ADD
4.4 配合SqlDelight
AutoValue配合SqlDelight效果会更好噢。
五 setter方法变种实现
AutoValue修饰的类是都是immutable不变的,所以就没有了setter的方法。 我们应该怎么样补救呢?
方法1: 重新new
这种情况适用于 不是频繁的需要setter的话,重新new是个不错的方法。
例如还是上面的bean,添加了两个create方法,和Builder。第二个create方法就可以用来重新new,然后setter最新的数据进来:
@AutoValue
public abstract class User {abstract String name();abstract String addr();abstract int age();abstract String gender();abstract String hobby();abstract String sign();//创建方法public static User create(String name, String addr, int age, String gender, String hobby, String sign) {return builder().name(name).addr(addr).age(age).gender(gender).hobby(hobby).sign(sign).build();}//setter的时候传递当前的user过来,这里重新builder,再设置public static Builder create(User user){return builder().name(user.name()).addr(user.addr()).age(user.age()).gender(user.gender()).hobby(user.hobby()).sign(user.sign());}public static Builder builder() {return new AutoValue_User.Builder();}@AutoValue.Builderpublic abstract static class Builder {public abstract Builder name(String name);public abstract Builder addr(String addr);public abstract Builder age(int age);public abstract Builder gender(String gender);public abstract Builder hobby(String hobby);public abstract Builder sign(String sign);public abstract User build();}}
使用,例如我要更新签名:
private void updateSign(User user){user = User.create(user).sign("新签名").build();}
方法2: 不要用AutoValue了
这种情况适用于你需要频繁的调用setter,如果用第一种方案的话,就需要频繁的new对象,对程序效率有大大的影响。
Android AutoValue使用和扩展库相关推荐
- java autovalue_Android AutoValue使用和扩展库
一.什么是AutoValue 意思就是自动值,谷歌出品,添加@AutoValue这样的注解 就能够自动生成代码,使得程序可能更短,更清晰. 支持Java1.6+ 首先看一个bean类,User.jav ...
- python android 扩展库,Python模块进阶、标准库、扩展库
模块进阶 Python有一套很有用的标准库(standard library).标准库会随着Python解释器,一起安装在你的电脑中的. 它是Python的一个组成部分.这些标准库是Python为你准 ...
- TVM apps extension示例扩展库
TVM apps extension示例扩展库 此文件夹包含TVM的示例扩展库.演示了其它库如何在C++和Python API中扩展TVM. 该库扩展了TVM的功能. python模块加载新的共享库, ...
- android好用的第三方库2018使用总结
不知不觉2018年已经过了大半,来总结一下今年用到的一些好用的框架和第三方库,包括App架构.异步通信库.注入注解框架.网络请求库.图片加载库.动画库.数据库.音频视频库.平台分享库.蓝牙库.权限请求 ...
- Android 开源项目android-open-project工具库解析之(一) 依赖注入,图片缓存,网络相关,数据库orm工具包,Android公共库...
一.依赖注入DI 通过依赖注入降低View.服务.资源简化初始化.事件绑定等反复繁琐工作 AndroidAnnotations(Code Diet) android高速开发框架 项目地址:https: ...
- WPF开源控件扩展库 - MaterialDesignExtensions
WPF开源控件扩展库 - MaterialDesignExtensions MaterialDesignExtensions仓库截图 logo Material Design Extensions 在 ...
- Android 开源组件和第三方库汇总
出自(https://github.com/Tim9Liu9/TimLiu-Android) TimLiu-Android 自己总结的Android开源项目及库. 1. github排名 https: ...
- Android开源项目以及开源库集合(持续更新中)
UI Awesome-MaterialDesign – MaterialDesignCenter改名为Awesome-MaterialDesign,优化了布局,新增了不少库. awesome-andr ...
- android 很多牛群叉界面库github地址
android 很多牛叉界面库github地址 点击可到达github-------https://github.com/Trinea/android-open-project Android开源项目 ...
最新文章
- 图片识别文字, OCR
- 【Paper】Few-Shot Charge Prediction with Discriminative Legal Attributes
- centos重启报错Umounting file systems:umount:/opt:device is busy
- python中二维列表的遍历方式(亲测)
- python 类属性排序_Python实现多属性排序的方法
- c# 从一个大图里截取图形
- 1644E. Expand the Path
- Cisco PT模拟实验(8) 三层交换机的基本配置
- 测试之法 —— mock object
- 利用SMS轻松实现资产管理,SMS2003系列之四
- Windows 10 Enterprise LTSC MSDN官方纯净版下载
- Mac - 当前位置打开终端
- 锂电池充电——充电保护电路
- 一文带你了解python opencv中霍夫变换(Hough transform)的常用操作
- 产品设计杂谈--微信篇
- fmt:formatNumber标签
- matlab留学生作业代做,代做DFT留学生作业、代写Matlab实验作业、Matlab程序语言作业调试、FFT课程作业代做代做数据库SQL|调试Matlab程序...
- ATM机程序Linux,c语言模拟银行ATM机程序
- 2D游戏知识点二、Unity 2D游戏主角基本功能和动画
- C++简易计算器的实现