Android AutoValue使用和擴(kuò)展庫(kù)
一、什么是AutoValue
意思就是自動(dòng)值,谷歌出品,添加@AutoValue這樣的注解 就能夠自動(dòng)生成代碼,使得程序可能更短,更清晰。 支持Java1.6+
github: https://github.com/google/auto/blob/master/value/userguide/index.md
首先看一個(gè)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代碼很多,到時(shí)候添加toString、hashCode、equals這些代碼就更麻煩了(雖然ide有快速生成),這時(shí)候AutoValue就來(lái)拯救世界了。
二、基本使用
一步一腳印
2.1 導(dǎo)包
初次使用需要注意,官方只說(shuō)了在module依賴,這樣會(huì)build失敗的,對(duì)于新手來(lái)說(shuō)會(huì)一臉懵逼,因?yàn)樾枰猘pt。
項(xiàng)目的build.gradle添加依賴:
dependencies {
//添加這行
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
在module的build.gradle依賴以下,當(dāng)前最新是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標(biāo)識(shí)bean
現(xiàn)在來(lái)重新編寫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一下,這時(shí)候就會(huì)生成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;
}
@Override
String name() {
return name;
}
@Override
String addr() {
return addr;
}
@Override
int age() {
return age;
}
@Override
String gender() {
return gender;
}
@Override
String hobby() {
return hobby;
}
@Override
String sign() {
return sign;
}
@Override
public String toString() {
return "User{"
+ "name=" + name + ", "
+ "addr=" + addr + ", "
+ "age=" + age + ", "
+ "gender=" + gender + ", "
+ "hobby=" + hobby + ", "
+ "sign=" + sign
+ "}";
}
@Override
public 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;
}
@Override
public 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;
}
}
這個(gè)類就是生成的類,里面就幫你編寫好了各種方法hashCode、toString、equals、getter和setter等等。
2.3 構(gòu)造方法
這時(shí)候構(gòu)造方法利用自己寫的一個(gè)方法來(lái)實(shí)現(xiàn)newAutoValue_User,在User類里面添加create方法進(jìn)行調(diào)用生成的AutoValue_User,這時(shí)候bean的方法這樣的:
@AutoValue
public abstract class User {
abstract String name();
abstract String addr();
abstract int age();
abstract String gender();
abstract String hobby();
abstract String sign();
//創(chuàng)建User,內(nèi)部調(diào)用的是AutoValue_User
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);
}
}
2.4 使用
使用User.create方法即可創(chuàng)建對(duì)應(yīng)User對(duì)象:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
User user = User.create("天平","廣東",21,"男","敲代碼","沒(méi)有個(gè)性簽名");
Log.e("@@", "onCreate: "+user.toString());
}
}
即可看到輸出
onCreate: User{name=天平, addr=廣東, age=21, gender=男, hobby=敲代碼, sign=沒(méi)有個(gè)性簽名}
三、擴(kuò)展api
你以為AutoValue的功能就那么少嗎 ? 錯(cuò),他還有很多擴(kuò)展api。
3.1 auto-value-parcel
當(dāng)User需要實(shí)現(xiàn)Parcelable接口的時(shí)候,AutoValue也可以幫你搞定了。
在基本的使用基礎(chǔ)上繼續(xù)導(dǎo)包(當(dāng)前最新是0.2.5):
github地址:https://github.com/rharter/auto-value-parcel
apt 'com.ryanharter.auto.value:auto-value-parcel:0.2.5' // 需要自定義TypeAdapter就要導(dǎo)入 compile 'com.ryanharter.auto.value:auto-value-parcel-adapter:0.2.5'
基本Parcelable
這時(shí)候把User實(shí)現(xiàn)接口即可:
@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繼承的原來(lái)的$AutoValue_User類,把Parcelable需要實(shí)現(xiàn)的方法放在了AutoValue_User類:
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.readString(),
in.readString(),
in.readInt(),
in.readString(),
in.readString(),
in.readString()
);
}
@Override
public 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);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name());
dest.writeString(addr());
dest.writeInt(age());
dest.writeString(gender());
dest.writeString(hobby());
dest.writeString(sign());
}
@Override
public int describeContents() {
return 0;
}
}
其他類型Parcelable
Parcel 這個(gè)擴(kuò)展支持Parcel類支持的所有類型,但有時(shí)您可能需要parcel其他類型,如SparseArray或ArrayMap。您可以使用自定義TypeAdapter執(zhí)行此操作(需要導(dǎo)入auto-value-parcel-adapter)
例如User里面有一個(gè)類型Date。這時(shí)候需要為Date定義一個(gè)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);
}
}
這里為延遲數(shù)據(jù)傳遞,新建一個(gè)SecondActivity,在MainActivit傳遞user過(guò)去
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
User user = User.create("天平","廣東",21,"男","敲代碼","沒(méi)有個(gè)性簽名",new Date());
startActivity(new Intent(this,SecondActivity.class).putExtra("bean",user));
}
}
SecondActivity.java
public class SecondActivity extends Activity {
@Override
protected 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=沒(méi)有個(gè)性簽名, date=Mon Mar 13 14:36:19 GMT+08:00 2017}
3.2 auto-value-gson
就是你的用了AutoValues來(lái)修飾定義了Bean對(duì)象,Gson的就不能按照平常的方式來(lái)解析了,需要改變一下。
普及知識(shí):
- Gson的TypeAapter可以理解成自定義序列化和返序列化。通過(guò)實(shí)現(xiàn)JsonSerializer和JsonDeserializer進(jìn)行序列化和反序列化,在Gson創(chuàng)建的時(shí)候registerTypeAdapter(你的自定義TypeAapter)。 具體請(qǐng)百度。
auto-value-gson 的github地址: https://github.com/rharter/auto-value-gson
導(dǎo)包(當(dāng)前最新是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修飾的對(duì)象,
這時(shí)候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();
//添加一個(gè)TypeAdapter<User>,這個(gè)TypeAdapter是Gson包里面的。
public static TypeAdapter<User> typeAdapter(Gson gson){
// AutoValue_User.GsonTypeAdapter 需要先make一下module之后才會(huì)生成
return new AutoValue_User.GsonTypeAdapter(gson)
.setDefaultAddr("默認(rèn)地址"); //還可以設(shè)置默認(rèn)值
}
}
- 注意: TypeAdapter,這個(gè)TypeAdapter是Gson包里面的。AutoValue_User.GsonTypeAdapter(gson) 需要先make一下module之后才會(huì)生成。
3.2.2 編寫TypeAdapterFactory
然后編寫對(duì)應(yīng)的編寫TypeAdapterFactory類,使用@GsonTypeAdapterFactory注解去修飾。
@GsonTypeAdapterFactory
public abstract class UserAdapterFactory implements TypeAdapterFactory {
// 靜態(tài)工廠方式
public static TypeAdapterFactory create() {
return new AutoValueGson_UserAdapterFactory();
}
}
3.2.3 Gson解析
上面搞好了之后,嘗試來(lái)解析json為User看看。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//json字符串
String json = "{\"name\":\"天平\",\"addr\":\"廣東\",\"age\":21,\"gender\":\"男\(zhòng)",\"hobby\":\"打代碼\",\"sign\":\"簽名\",\"date\":\"2017-3-13 14:36:19\"}";
//初始化Gson
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(UserAdapterFactory.create()) //注冊(cè)自定義的TypeAdapterFactory
.setDateFormat("yyyy-MM-dd HH:mm:ss") //設(shè)置json里面的Date格式
.create();
//開始解析
User user = gson.fromJson(json,User.class);
//輸出結(jié)果
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}
四、小細(xì)節(jié)
4.1 Gson泛型支持
如果你的bean類里面有泛型,這時(shí)候你的TypeAdapter也需要泛型,還要添加參數(shù)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 可選配置
添加了下面的設(shè)置,maps/collections將默認(rèn)為它們的空類型(例如List - > Collections.emptyList()) 值為true或false。
apt {
arguments {
autovaluegson.defaultCollectionsToEmpty 'true'
}
}
4.3 AutoValue plugin插件
可以生成create Builder等代碼,不過(guò)不能生成TypeAdapter代碼:
插件倉(cāng)庫(kù)搜索: AutoValue plugin
開源地址: https://github.com/afcastano/AutoValuePlugin
使用方法: 安裝插件重啟了As之后,在Bean里面Alt+回車 即可ADD
4.4 配合SqlDelight
AutoValue配合SqlDelight效果會(huì)更好噢。
五 setter方法變種實(shí)現(xiàn)
AutoValue修飾的類是都是immutable不變的,所以就沒(méi)有了setter的方法。 我們應(yīng)該怎么樣補(bǔ)救呢?
方法1: 重新new
這種情況適用于 不是頻繁的需要setter的話,重新new是個(gè)不錯(cuò)的方法。
例如還是上面的bean,添加了兩個(gè)create方法,和Builder。第二個(gè)create方法就可以用來(lái)重新new,然后setter最新的數(shù)據(jù)進(jìn)來(lái):
@AutoValue
public abstract class User {
abstract String name();
abstract String addr();
abstract int age();
abstract String gender();
abstract String hobby();
abstract String sign();
//創(chuàng)建方法
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的時(shí)候傳遞當(dāng)前的user過(guò)來(lái),這里重新builder,再設(shè)置
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.Builder
public 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了
這種情況適用于你需要頻繁的調(diào)用setter,如果用第一種方案的話,就需要頻繁的new對(duì)象,對(duì)程序效率有大大的影響。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
- Android用戶輸入自動(dòng)提示控件AutoCompleteTextView使用方法
- Android自動(dòng)獲取輸入短信驗(yàn)證碼庫(kù)AutoVerifyCode詳解
- Android AutoWrapTextView中英文排版問(wèn)題的解決方法
- Android中使用 AutoCompleteTextView 實(shí)現(xiàn)手機(jī)號(hào)格式化附帶清空歷史的操作
- Android自動(dòng)編輯文本框(AutoCompleteTextView)使用方法詳解
- Android中AutoCompleteTextView自動(dòng)提示
- Android仿新浪微博oauth2.0授權(quán)界面實(shí)現(xiàn)代碼(2)
- android中AutoCompleteTextView的簡(jiǎn)單用法(實(shí)現(xiàn)搜索歷史)
- Android仿百度谷歌搜索自動(dòng)提示框AutoCompleteTextView簡(jiǎn)單應(yīng)用示例
- 關(guān)于Android HTML5 audio autoplay無(wú)效問(wèn)題的解決方案
- Android AutoCompleteTextView自動(dòng)提示文本框?qū)嵗a
- Android App開發(fā)的自動(dòng)化測(cè)試框架UI Automator使用教程
- Android中AutoCompleteTextView與TextWatcher結(jié)合小實(shí)例
相關(guān)文章
Android開發(fā)之Service用法實(shí)例
這篇文章主要介紹了Android開發(fā)之Service用法,實(shí)例分析了Android中Service的功能及使用技巧,需要的朋友可以參考下2015-05-05
Android DownloadMananger管理器實(shí)現(xiàn)下載圖片功能
Android DownloadMananger類似于下載隊(duì)列,管理所有當(dāng)前正在下載或者等待下載的項(xiàng)目,他可以維持HTTP鏈接,并且在隊(duì)列中的下載項(xiàng)目一旦失敗,還能自動(dòng)重新下載2023-01-01
Android HttpURLConnection斷點(diǎn)下載(單線程)
這篇文章主要為大家詳細(xì)介紹了Android HttpURLConnection斷點(diǎn)下載的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
android studio與手機(jī)連接調(diào)試步驟詳解
這篇文章主要為大家詳細(xì)介紹了android studio與手機(jī)連接調(diào)試步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android開發(fā)實(shí)現(xiàn)錄屏小功能
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)錄屏小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
模擬按Home鍵退出應(yīng)用的簡(jiǎn)單方法(分享)
下面小編就為大家?guī)?lái)一篇模擬按Home鍵退出應(yīng)用的簡(jiǎn)單方法(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android Fragment實(shí)現(xiàn)底部通知欄
這篇文章主要為大家詳細(xì)介紹了Android Fragment實(shí)現(xiàn)底部通知欄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
Android自定義ViewGroup之CustomGridLayout(一)
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup之CustomGridLayout的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-09-09
Android編程入門之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析
這篇文章主要介紹了Android編程入門之HelloWorld項(xiàng)目目錄結(jié)構(gòu)分析,較為詳細(xì)的分析了Android項(xiàng)目的目錄結(jié)構(gòu)與具體作用,需要的朋友可以參考下2015-12-12

