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

ぼくにもできた Annotation Processing

ぼくにもできた Annotation Processing

ぼくにもできた
Annotation Processing

Fumihiko Shiroyama

January 20, 2017
Tweet

More Decks by Fumihiko Shiroyama

Other Decks in Technology

Transcript

  1. ར༻ྫ " ੜ੒͞ΕͨίʔυΛͦͷ··ར༻͢ΔλΠϓ w "OESPJE"OOPUBUJPOT FUDʜ # ॲཧΛҕৡ͢ΔλΠϓ w #VUUFS,OJGF

    1FSNJTTJPOT%JTQBUDIFS FUDʜ Ҡৡͷίʔυ͕ෆཁ͕ͩ ར༻ଆͰੜ੒͞ΕͨίʔυΛҙࣝ͢Δඞཁ͕͋Δ .BOJGFTUʹొ࿥͕ඞཁ౳ Ҡৡͷίʔυ͕ඞཁ͕ͩ ݩΫϥε͸ͦͷ··ͰΑ͍
  2. MJCSBSZNPEVMF w +BWB-JCSBSZ"OESPJE-JCSBSZ w "OOPUBUJPOΫϥε΍ϥΠϒϥϦͱͯ͠ఏڙ͢Δ࣮ॲཧΛ ॻ͍ͨΫϥε͕ॴଐ w +BWB POMZ+BDL 

    w ίϯύΠϧ࣌ͷΈඞཁͳ৔߹͸QSPWJEFE w BQQϞδϡʔϧ͔ΒϥΠϒϥϦͷίʔυΛࢀর͢Δ৔߹ ͸DPNQJMF
  3. @MyCoolAnnotation
 public class SampleClass {
 @MyCoolAnnotation
 final String text;
 


    public SampleClass(String text) {
 this.text = text;
 }
 } TBNQMFNPEVMF
  4. QSPDFTTPSNPEVMF dependencies {
 compile project(":library")
 compile 'com.squareup:javapoet:1.8.0'
 compile 'com.google.auto.service:auto-service:1.0-rc2'
 compile

    'com.google.android:android:4.1.1.4'
 }
 sourceSets {
 main {
 java {
 srcDirs = [‘src/main/java', '../library/src/main/java']
 }
 }
 }
  5. QSPDFTTPSNPEVMF dependencies {
 compile project(":library")
 compile 'com.squareup:javapoet:1.8.0'
 compile 'com.google.auto.service:auto-service:1.0-rc2'
 compile

    'com.google.android:android:4.1.1.4'
 }
 sourceSets {
 main {
 java {
 srcDirs = [‘src/main/java', '../library/src/main/java']
 }
 }
 } BOESPJEMJCSBSZΛࢀর͢Δ৔߹ BOESPJEMJCSBSZΛࢀর͢Δ৔߹
  6. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF
  7. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF 1SPDFTTPS͸͜ͷந৅ΫϥεΛܧঝͯ͠ ࡞Δͷ͕ศར
  8. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF ίϯύΠϧ࣌ʹ͜ͷ1SPDFTTPS͕࣮ߦ͞ΕΔ
  9. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF ॲཧର৅ͷΞϊςʔγϣϯΛ4FUͰࢦఆ
  10. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF αϙʔτ্ݶͷ+BWBόʔδϣϯ
  11. @AutoService(Processor.class)
 public class MyProcessor extends AbstractProcessor {
 @Override
 public Set<String>

    getSupportedAnnotationTypes() {
 return ImmutableSet.of(MyCoolAnnotation.class.getName());
 }
 
 @Override
 public SourceVersion getSupportedSourceVersion() {
 return SourceVersion.latest();
 }
 
 @Override
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
 return false;
 }
 } QSPDFTTPSNPEVMF ϓϩηοαʔʹΑΔॲཧຊମ
  12. QSPDFTTPSNPEVMF private Elements elementUtils;
 private Types typeUtils;
 private Messager messager;


    private Filer filer;
 
 @Override
 public synchronized void init(ProcessingEnvironment processingEnvironment) {
 super.init(processingEnvironment);
 
 elementUtils = processingEnvironment.getElementUtils();
 typeUtils = processingEnvironment.getTypeUtils();
 messager = processingEnvironment.getMessager();
 filer = processingEnvironment.getFiler();
 } ศརͳϢʔςΟϦςΟ܈
  13. QSPDFTTPSNPEVMF TypeElement classElement = roundEnvironment.getElementsAnnotatedWith(MyCoolAnnotation.class)
 .stream()
 .filter(element -> element.getKind() ==

    ElementKind.CLASS)
 .map(element -> (TypeElement) element)
 .findFirst()
 .get();
 
 String className = classElement.getSimpleName().toString();
 
 TypeSpec typeSpec = TypeSpec.classBuilder("Sub" + className).build();
 JavaFile javaFile = JavaFile.builder("com.example", typeSpec).build();
 try {
 javaFile.writeTo(filer);
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
 } ΞϊςʔγϣϯʹରԠ͢Δཁૉ
  14. QSPDFTTPSNPEVMF TypeElement classElement = roundEnvironment.getElementsAnnotatedWith(MyCoolAnnotation.class)
 .stream()
 .filter(element -> element.getKind() ==

    ElementKind.CLASS)
 .map(element -> (TypeElement) element)
 .findFirst()
 .get();
 
 String className = classElement.getSimpleName().toString();
 
 TypeSpec typeSpec = TypeSpec.classBuilder("Sub" + className).build();
 JavaFile javaFile = JavaFile.builder("com.example", typeSpec).build();
 try {
 javaFile.writeTo(filer);
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
 } ΫϥεΛऔಘ
  15. QSPDFTTPSNPEVMF TypeElement classElement = roundEnvironment.getElementsAnnotatedWith(MyCoolAnnotation.class)
 .stream()
 .filter(element -> element.getKind() ==

    ElementKind.CLASS)
 .map(element -> (TypeElement) element)
 .findFirst()
 .get();
 
 String className = classElement.getSimpleName().toString();
 
 TypeSpec typeSpec = TypeSpec.classBuilder("Sub" + className).build();
 JavaFile javaFile = JavaFile.builder("com.example", typeSpec).build();
 try {
 javaFile.writeTo(filer);
 } catch (IOException e) {
 messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage());
 } +BWBΫϥεΛੜ੒
  16. public interface Greeter { String sayHello(); String sayHello(String toWhom); }

    public class EnglishGreeter implements Greeter { @Override public String sayHello() { return sayHello("ANONYMOUS"); } @Override public String sayHello(String toWhom) { return String.format("Hello %s !", toWhom); } } $VDLPP ΠϯλϑΣʔε
  17. public interface Greeter { String sayHello(); String sayHello(String toWhom); }

    public class EnglishGreeter implements Greeter { @Override public String sayHello() { return sayHello("ANONYMOUS"); } @Override public String sayHello(String toWhom) { return String.format("Hello %s !", toWhom); } } $VDLPP ࣮૷
  18. @Delegate public abstract class EnglishGreeterWithRecording implements Greeter { @By final

    EnglishGreeter englishGreeter = new EnglishGreeter(); @Override public String sayHello(String toWhom) { // do anything you like here return englishGreeter.sayHello(toWhom); } } $VDLPP
  19. @Delegate public abstract class EnglishGreeterWithRecording implements Greeter { @By final

    EnglishGreeter englishGreeter = new EnglishGreeter(); @Override public String sayHello(String toWhom) { // do anything you like here return englishGreeter.sayHello(toWhom); } } $VDLPP !"CTUSBDU !%FMFHBUF
  20. @Delegate public abstract class EnglishGreeterWithRecording implements Greeter { @By final

    EnglishGreeter englishGreeter = new EnglishGreeter(); @Override public String sayHello(String toWhom) { // do anything you like here return englishGreeter.sayHello(toWhom); } } $VDLPP JNQMFNFOUT
  21. @Delegate public abstract class EnglishGreeterWithRecording implements Greeter { @By final

    EnglishGreeter englishGreeter = new EnglishGreeter(); @Override public String sayHello(String toWhom) { // do anything you like here return englishGreeter.sayHello(toWhom); } } $VDLPP ੜ੒͞ΕͨΫϥε͸ ະ࣮૷ͷϝιου͸ !#Zम০ͨ͠Πϯελϯεʹ ͢΂ҕৡ͞ΕΔ
  22. $VDLPP OFX*OTUBODF Ͱऔಘ // in your code EnglishGreeterWithRecording greeter =

    EnglishGreeterWithRecordingImpl.newInstance(new EnglishGreeter());
  23. void fetchAsynchronously() { /* do heavy asynchronous task here */

    doCallback("finished!"); } void doCallback(@NonNull String message) { FinishDialog.newInstance().show(getSupportFragmentManager(), "TAG"); } 7VMUVSF
  24. void fetchAsynchronously() { /* do heavy asynchronous task here */

    doCallback("finished!"); } void doCallback(@NonNull String message) { FinishDialog.newInstance().show(getSupportFragmentManager(), "TAG"); } 7VMUVSF ඇಉظॲཧ
  25. void fetchAsynchronously() { /* do heavy asynchronous task here */

    doCallback("finished!"); } void doCallback(@NonNull String message) { FinishDialog.newInstance().show(getSupportFragmentManager(), "TAG"); } 7VMUVSF ίʔϧόοΫ PO1BVTFҎ߱͸Ϋϥογϡ
  26. 7VMUVSF @ObserveLifecycle public class YourActivity extends AppCompatActivity { void fetchAsynchronously()

    { SafeMainActivity.doCallbackSafely("finished!"); } @SafeCallback void doCallback(@NonNull String message) { FinishDialog.newInstance().show(getSupportFragmentManager(), "TAG"); } }
  27. 7VMUVSF @ObserveLifecycle public class YourActivity extends AppCompatActivity { void fetchAsynchronously()

    { SafeMainActivity.doCallbackSafely("finished!"); } @SafeCallback void doCallback(@NonNull String message) { FinishDialog.newInstance().show(getSupportFragmentManager(), "TAG"); } } !4BGF$BMMCBDL ͔ΘΓʹͪ͜ΒΛݺͼग़͢
  28. 7VMUVSF @Override protected void onResume() { super.onResume(); SafeMainActivity.register(this); } @Override

    protected void onPause() { SafeMainActivity.unregister(); super.onPause(); }
  29. 7VMUVSF @Override protected void onResume() { super.onResume(); SafeMainActivity.register(this); } @Override

    protected void onPause() { SafeMainActivity.unregister(); super.onPause(); } ҕৡ