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

AutoValue Extensions (NYC Android Meetup, March 2016)

AutoValue Extensions (NYC Android Meetup, 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.

Presented at: http://www.meetup.com/android-developers-nyc/events/228554404/

Video: https://www.youtube.com/watch?v=FfBBTHkRC-o

Jake Wharton

March 08, 2016
Tweet

More Decks by Jake Wharton

Other Decks in Technology

Transcript

  1. Value Types? • Basically everything is mutable in Java. •

    "Beans" with getters and setters • Collections
  2. Value Types? • Basically everything is mutable in Java. •

    "Beans" with getters and setters • Collections • Arrays
  3. Value Types? • Basically everything is mutable in Java. •

    "Beans" with getters and setters • Collections • Arrays • Mutator methods
  4. Value Types? • Basically everything is mutable in Java. •

    "Beans" with getters and setters • Collections • Arrays • Mutator methods • Non-scalar "constants"
  5. Value Types public class Payment {
 public long id();
 public

    long amount();
 public String note();
 }X
  6. Value Types public final class Payment {
 public long id();


    public long amount();
 public String note();
 }X
  7. Value Types public final class Payment {
 private final long

    id;
 
 public long id() {
 return id;
 }Y
 public long amount();
 public String note();
 }X
  8. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note();
 }X
  9. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final String note;
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note() {
 return note;
 }W
 }X
  10. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final String note;
 
 public Payment(long id, long amount, String note) {
 this.id = id;
 this.amount = amount;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note() {
 return note;
 }W
 }X
  11. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final String note;
 
 public Payment(long id, long amount, String note) {
 this.id = id;
 this.amount = amount;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note() {
 return note;
 }W
 
 @Override public String toString() {
 return "Payment{" +
 "id=" + id +
 ", amount=" + amount +
 ", note='" + note + '\'' +
 '}';
 }E
 }X
  12. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final String note;
 
 public Payment(long id, long amount, String note) {
 this.id = id;
 this.amount = amount;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note() {
 return note;
 }W
 
 @Override public String toString() {
 return "Payment{" +
 "id=" + id +
 ", amount=" + amount +
 ", 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
 && 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 + note.hashCode();
 return result;
 }T
 }X
  13. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final String note;
 
 public Payment(long id, long amount, String note) {
 this.id = id;
 this.amount = amount;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public String note() {
 return note;
 }W
 
 @Override public String toString() {
 return "Payment{" +
 "id=" + id +
 ", amount=" + amount +
 ", 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
 && 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 + note.hashCode();
 return result;
 }T
 }X public Currency currency();
  14. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final Currency currency;
 private final String note;
 
 public Payment(long id, long amount, Currency currency, String note) {
 this.id = id;
 this.amount = amount;
 this.currency = currency;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public Currency currency() {
 return currency;
 }U
 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
  15. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final Currency currency;
 private final String note;
 
 public Payment(long id, long amount, Currency currency, String note) {
 this.id = id;
 this.amount = amount;
 this.currency = currency;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public Currency currency() {
 return currency;
 }U
 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 1 2 3 4 5 6 7 8 Field Constructor Parameter Constructor Statement Method Signature Method Statement toString() Expression equals() Expression hashCode() Expression
  16. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final Currency currency;
 private final String note;
 
 public Payment(long id, long amount, Currency currency, String note) {
 this.id = id;
 this.amount = amount;
 this.currency = currency;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public Currency currency() {
 return currency;
 }U
 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
  17. Value Types public final class Payment {
 private final long

    id;
 private final long amount;
 private final Currency currency;
 private final String note;
 
 public Payment(long id, long amount, Currency currency, String note) {
 this.id = id;
 this.amount = amount;
 this.currency = currency;
 this.note = note;
 }Q
 
 public long id() {
 return id;
 }Y
 public long amount() {
 return amount;
 }Z
 public Currency currency() {
 return currency;
 }U
 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 public class Payment {
 public long id();
 public long amount();
 public Currency currency();
 public String note();
 }X
  18. AutoValue! public class Payment {
 public long id();
 public long

    amount();
 public Currency currency();
 public String note();
 }X
  19. AutoValue! @AutoValue public class Payment {
 public long id();
 public

    long amount();
 public Currency currency();
 public String note();
 }X
  20. AutoValue! @AutoValue public abstract class Payment {
 public abstract long

    id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  21. 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
  22. 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
  23. 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 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
  24. AutoValue Extensions @AutoValue public abstract class Payment {
 public abstract

    long id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  25. AutoValue Extensions @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
  26. AutoValue Extensions @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
  27. AutoValue Extensions @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
  28. AutoValue Extensions @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)
  29. AutoValue Extensions @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)
  30. AutoValue Extensions @AutoValue public abstract class Payment3{
 public abstract long

    id();
 public abstract long amount();
 public abstract Currency currency();
 public abstract String note();
 }X
  31. 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 */
  32. AutoValue Extensions @AutoValue public abstract class Payment1implements2Parcelable3{3 /* abstract properties

    */ }X final class AutoValue_Payment1extends2Payment { /* value type implementation */ }Y
  33. 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
  34. 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 */
  35. 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 */
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  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;
 }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);
 }
  45. Extension API public boolean applicable(Context context) Parcelable extension Parcelable extension

    @AutoValue public abstract class Payment {} @AutoValue public abstract class Payment implements Parcelable {} false
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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);
 }
  53. 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);
 }
  54. 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
  55. 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
  56. 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);
 }
  57. 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);
 }
  58. Extension API public Set<String> consumeProperties(Context context) @AutoValue public abstract class

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

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

    Payment implements Parcelable { public abstract String note(); } Extension [ ] [ "note", "describeContents" ]
  61. 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" ]
  62. 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);
 }
  63. 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);
 }
  64. 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
  65. 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 ??????