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

AutoValue Extensions (NYC Android Meetup, March...

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 ??????