1. 程式人生 > >Google AutoValue詳解

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物件會創造很大的價值。

詳細使用及原理戳這裡