您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何在Android中使用AutoValue擴展庫,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
一、什么是AutoValue
意思就是自動值,谷歌出品,添加@AutoValue
這樣的注解 就能夠自動生成代碼,使得程序可能更短,更清晰。
首先看一個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; } @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; } }
這個類就是生成的類,里面就幫你編寫好了各種方法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_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方法即可創建對應User對象:
public class MainActivity extends AppCompatActivity { @Override protected 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>() { @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 這個擴展支持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 { @Override protected 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 { @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=沒有個性簽名, 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 { @Override protected 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\"}"; //初始化Gson Gson 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.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(); }
上述內容就是如何在Android中使用AutoValue擴展庫,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。