Google AutoValue詳解
背景
首先說Android Model,在開發中網路請求,以及資料庫操作等,我們都會定義一個Model,不同人對這個的說法不一樣,比如有Entry,Bean,Pojo。
通常對於實體類,我們需要做如下幾件事情:
- 構成方法:自定義構造方法,如果實體比較複雜,可能會用到工廠模式或者是建造者模式
- 序列化:比如實現Serializable介面,Parcelable介面。
- Json解析:有時候直接使用的是json資料,比如@SerializedName註解。
- 自定義方法:對Model的欄位有setter,getter方法,toString的實現,在處理hash的時候,需要實現equals和hashcode方法。
這些實際上eclipse及Android Studio都已經幫我們做好了。
通常的我們看到的java bean是這樣的
public class NvramInfo {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NvramInfo nvramInfo = (NvramInfo) o;
return Objects.equals(key, nvramInfo.key) &&
Objects.equals(value , nvramInfo.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
@Override
public String toString() {
return "NvramInfo{" +
"key='" + key + '\'' +
", value='" + value + '\'' +
'}';
}
}
簡介
為了是的java bean的看起來更加簡介優雅,我們來看看Google AutoValue 如何處理java bean的。
那麼AutoValue是什麼呢?來看下官方總結解釋的:
一個生成Java不可變的值型別工具,仔細研讀原始碼後,使用的技術是Java Apt
AutoValue - Immutable value-type code generation for Java 1.6+.
簡單使用
基於Android Studio 3.1.2, 支援Android的gradle外掛版本為3.0.1
在工程根目錄下新增如下gradle外掛版本
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
app Module中新增如下依賴:
annotationProcessor 'com.google.auto.value:auto-value:1.5.2'
compileOnly 'com.google.auto.value:auto-value:1.5.2'
通過AutoValue構造的Java Bean如下:
package com.grandstream.gsmarket.data.entity;
import android.os.Parcelable;
import com.google.auto.value.AutoValue;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
@AutoValue
public abstract class AppInfo implements Parcelable {
/**
* @Description: TODO(新增屬性註釋)
*/
//private static final long serialVersionUID = 1L;
public static JsonAdapter<AppInfo> jsonAdapter(Moshi moshi) {
return new AutoValue_AppInfo.MoshiJsonAdapter(moshi);
}
public static Builder builder() {
return new AutoValue_AppInfo.Builder();
}
/**
* @Description: 主鍵id
*/
public abstract String appname();
public abstract String appcode();
public abstract String version();
public abstract String size();
public abstract String packagename();
public abstract String downloadurl();
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder appname(String appname);
public abstract Builder appcode(String appcode);
public abstract Builder version(String version);
public abstract Builder size(String size);
public abstract Builder packagename(String packagename);
public abstract Builder downloadurl(String downloadurl);
public abstract AppInfo build();
}
}
在上面的java bean的構造中,我們採用了建造者模式完成,同時實現了Parcelable 及moshi Json的轉化功能。
建立AutoValue與moshi Json的關係需要如下依賴:
implementation 'com.ryanharter.auto.value:auto-value-moshi-annotations:0.4.3'
annotationProcessor 'com.ryanharter.auto.value:auto-value-moshi:0.4.3'
implementation 'com.ryanharter.auto.value:auto-value-parcel-adapter:0.2.5'
annotationProcessor 'com.ryanharter.auto.value:auto-value-parcel:0.2.5'
編譯後生成的相關類關係圖
從類關係圖可以看出,最終會生成一個AutoValue_AppInfo的類,實現所有的註解功能。在實際使用,建立物件時候,通過靜態構造方法完成
public static Builder builder() {
return new AutoValue_AppInfo.Builder();
}
檢視最終類AutoValue_AppInfo程式碼可以看出,所有的變數及最終的類都是final型別的,程式碼裡同時也實現了equals、hashcode、toString方法。
Immutable/Value types
剛剛上面說到,所有的欄位都是final型別,那麼而且實現類也是final的,有個專業術語叫Immutable。一個數據物件一旦構造完成,就再也無法修改了。這樣有什麼好處呢?最大的好處就是多執行緒訪問可以省去很多同步控制,因為它們是不可變的,一旦構造完成,就不會存在多執行緒競爭訪問問題了。多執行緒最麻煩的處理就是控制好讀寫問題,如果大家都是讀,那麼就不存控制了,所以省去了很多同步操作。
舉個Java中的例子:String和StringBuilder,String是immutable的,每次對於String物件的修改都將產生一個新的String物件,而原來的物件保持不變,而StringBuilder是mutable,因為每次對於它的物件的修改都作用於該物件本身,並沒有產生新的物件。
Immutable objects 比傳統的mutable物件在多執行緒應用中更具有優勢,它不僅能夠保證物件的狀態不被改變,而且還可以不使用鎖機制就能被其他執行緒共享。
總結下Immutable物件的優缺點:
優點
1. Immutable物件是執行緒安全的,可以不用被synchronize就在併發環境中共享
2. Immutable物件簡化了程式開發,因為它無需使用額外的鎖機制就可以線上程間共享
3. Immutable物件提高了程式的效能,因為它減少了synchroinzed的使用
4. Immutable物件是可以被重複使用的,你可以將它們快取起來重複使用,就像字串字面量和整型數字一樣。你可以使用靜態工廠方法來提供類似於valueOf()這樣的方法,它可以從快取中返回一個已經存在的Immutable物件,而不是重新建立一個。
缺點
Immutable也有一個缺點就是會製造大量垃圾,由於他們不能被重用而且對於它們的使用就是”用“然後”扔“,字串就是一個典型的例子,它會創造很多的垃圾,給垃圾收集帶來很大的麻煩。當然這只是個極端的例子,合理的使用immutable物件會創造很大的價值。