Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AutoValue Extensions (Square NYC, March 2016)

AutoValue Extensions (Square NYC, March 2016)

Google's AutoValue library provides easy value types in Java through code generation and its forthcoming release has a powerful new feature: extensions. This talk will introduce the extensions feature, cover useful extensions for Android, and offer tips for building your own.

Video: https://www.youtube.com/watch?v=Kl2xZufgW14

Jake Wharton

March 10, 2016
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. AutoValue @AutoValue public abstract class Payment {
 public abstract long

    id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  2. AutoValue @AutoValue
 public abstract class Payment { 
 public static

    Payment create(
 long id, long amount, Currency currency, String note) {
 return new AutoValue_Payment(id, amount, currency, note);
 }Z
 
 public abstract long id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  3. AutoValue @AutoValue
 public abstract class Payment { 
 public static

    Payment create(
 long id, long amount, Currency currency, String note) {
 return new AutoValue_Payment(id, amount, currency, note);
 }Z
 
 public abstract long id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  4. AutoValue Extensions @AutoValue
 public abstract class Payment { 
 public

    static Payment create(
 long id, long amount, Currency currency, String note) {
 return new AutoValue_Payment(id, amount, currency, note);
 }Z
 
 public abstract long id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X final class AutoValue_Payment extends Payment {
 private final long id;
 private final long amount;
 private final Currency currency;
 private final String note;
 
 AutoValue_Payment(long id, long amount, Currency currency, String note) {
 this.id = id;
 this.amount = amount;
 this.currency = currency;
 this.note = note;
 }Q
 
 @Override public long id() {
 return id;
 }Y
 @Override public long amount() {
 return amount;
 }Z
 @Override public Currency currency() {
 return currency;
 }U
 @Override public String note() {
 return note;
 }W
 
 @Override public String toString() {
 return "Payment{" +
 "id=" + id +
 ", amount=" + amount +
 ", currency=" + currency +
 ", note='" + note + '\'' +
 '}';
 }E
 
 @Override public boolean equals(Object o) {
 if (this == o) return true;
 if (!(o instanceof Payment)) return false;
 Payment other = (Payment) o;
 return id == other.id
 && amount == other.amount
 && currency.equals(other.currency)
 && note.equals(other.note);
 }R
 
 @Override public int hashCode() {
 int result = (int) (id ^ (id >>> 32));
 result = 31 * result + (int) (amount ^ (amount >>> 32));
 result = 31 * result + currency.hashCode();
 result = 31 * result + note.hashCode();
 return result;
 }T
 }X
  5. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X AutoValue Extensions
  6. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X Ok, awesome! Now how do I use it with ? Parcelable AutoValue Extensions
  7. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X Ok, awesome! Now how do I use it with ? Parcelable Gson AutoValue Extensions
  8. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X Ok, awesome! Now how do I use it with ? Parcelable Gson Cursors AutoValue Extensions
  9. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X Ok, awesome! Now how do I use it with ? Parcelable Gson Cursors (whatever) AutoValue Extensions
  10. @AutoValue public abstract class Payment {
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X Ok, awesome! Now how do I use it with ? Parcelable Gson Cursors (whatever) AutoValue Extensions
  11. AutoValue @AutoValue public abstract class Payment3{
 public abstract long id();


    public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X AutoValue Extensions
  12. AutoValue Extensions @AutoValue public abstract class Payment1implements2Parcelable3{3
 public abstract long

    id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X /* abstract properties */
  13. AutoValue Extensions @AutoValue public abstract class Payment1implements2Parcelable3{3 /* abstract properties

    */ }X final class AutoValue_Payment1extends2Payment { /* value type implementation */ }Y
  14. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  15. final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */ }Z /*

    abstract properties */ abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y AutoValue Extensions @AutoValue public abstract class Payment1implements2Parcelable3{3
 public abstract long id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X /* abstract properties */
  16. final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */ }Z /*

    abstract properties */ abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y AutoValue Extensions @AutoValue public abstract class Payment1implements2Parcelable3{3
 public abstract long id();
 public abstract long amount();
 public abstract Currency currency();
 @Redacted public abstract String note();
 }X /* abstract properties */
  17. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  18. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2$$AutoValue_Payment { /* value type implementation (without toString) */ }Y abstract class $$AutoValue_Payment1extends2Payment { /* redacted toString implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  19. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2$$AutoValue_Payment { /* value type implementation (without toString) */ }Y abstract class $$AutoValue_Payment1extends2Payment { /* redacted toString implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  20. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2$$AutoValue_Payment { /* value type implementation (without toString) */ }Y abstract class $$AutoValue_Payment1extends2Payment { /* redacted toString implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  21. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2$$AutoValue_Payment { /* value type implementation (without toString) */ }Y abstract class $$AutoValue_Payment1extends2Payment { /* redacted toString implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  22. AutoValue Extensions final class AutoValue_Payment1extends2$AutoValue_Payment { /* parcelable implementation */

    }Z abstract class $AutoValue_Payment1extends2$$AutoValue_Payment { /* value type implementation (without toString) */ }Y abstract class $$AutoValue_Payment1extends2Payment { /* redacted toString implementation */ }Y @AutoValue public abstract class Payment1implements2Parcelable { /* abstract properties */ }X
  23. Available Extensions • Parcelable: github.com/rharter/auto-value-parcel • Redacted: github.com/square/auto-value-redacted • Gson:

    github.com/rharter/auto-value-gson • Moshi: github.com/rharter/auto-value-moshi • Cursor: github.com/gabrielittner/auto-value-cursor • "with"ers: github.com/gabrielittner/auto-value-with
  24. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  25. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }X
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  26. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} false
  27. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} false true
  28. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    Redacted extension @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} @AutoValue public abstract class Payment { public abstract String note(); } false true
  29. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    Redacted extension @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} @AutoValue public abstract class Payment { public abstract String note(); } false true false
  30. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    Redacted extension Redacted extension @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} @AutoValue public abstract class Payment { public abstract String note(); } @AutoValue public abstract class Payment { @Redacted public abstract String note(); } false true false
  31. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    Redacted extension Redacted extension @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} @AutoValue public abstract class Payment { public abstract String note(); } @AutoValue public abstract class Payment { @Redacted public abstract String note(); } false true false true
  32. Extension API public boolean applicable(Context context) false true final class

    AutoValue_Payment1extends2Payment { /* value type implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X final class AutoValue_Payment1extends2$AutoValue_Payment { /* value type implementation */ }Y abstract class $AutoValue_Payment1extends2Payment { /* extension implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X
  33. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }X
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  34. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  35. Extension API public boolean mustBeFinal(Context context) false true final class

    AutoValue_Payment1extends2$AutoValue_Payment { /* extension implementation */ }Y abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X final class AutoValue_Payment1extends2$AutoValue_Payment { /* value type implementation */ }Y abstract class $AutoValue_Payment1extends2Payment { /* extension implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X
  36. Extension API public boolean mustBeFinal(Context context) false true final class

    AutoValue_Payment1extends2$AutoValue_Payment { /* extension implementation */ }Y abstract class $AutoValue_Payment1extends2Payment { /* value type implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X final class AutoValue_Payment1extends2$AutoValue_Payment { /* value type implementation */ }Y abstract class $AutoValue_Payment1extends2Payment { /* extension implementation */ }Y @AutoValue public abstract class Payment1{3 /* abstract properties */ }X
  37. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  38. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  39. Extension API public Set<String> consumeProperties(Context context) @AutoValue public abstract class

    Payment implements Parcelable { public abstract String note(); }
  40. Extension API public Set<String> consumeProperties(Context context) @AutoValue public abstract class

    Payment implements Parcelable { public abstract String note(); } Extension [ ]
  41. Extension API public Set<String> consumeProperties(Context context) @AutoValue public abstract class

    Payment implements Parcelable { public abstract String note(); } Extension [ ] [ "note", "describeContents" ]
  42. Extension API public Set<String> consumeProperties(Context context) @AutoValue public abstract class

    Payment implements Parcelable { public abstract String note(); } Extension [ ] [ "note", "describeContents" ] @AutoValue public abstract class Payment implements Parcelable { public abstract String note(); } Extension [ "describeContents" ] [ "note" ]
  43. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  44. Extension API public abstract class AutoValueExtension {
 public boolean applicable(Context

    context) {
 return false;
 }
 
 public boolean mustBeFinal(Context context) {
 return false;
 }
 
 public Set<String> consumeProperties(Context context) {
 return Collections.emptySet();
 }
 
 public abstract String generateClass(Context context, String className, String classToExtend, boolean isFinal);
 }
  45. Building Extensions • Model it after the existing extensions •

    Try to play nice with other extensions • JavaPoet: github.com/square/javapoet • Truth: github.com/google/truth • compile-testing: github.com/google/compile-testing • auto/service: github.com/google/auto
  46. 1.2-SNAPSHOT?!? Big Bang Heat death of universe AutoValue 1.1 released

    (10 months ago) Extensions merged (9 months ago) AutoValue 1.2 released ?????? (not to scale)