14. How we use it
dependencies {
implementation 'com.google.dagger:dagger:2.x'
kapt ‘com.google.dagger:dagger-compiler:2.x'
}
kapt stands for
Kotlin annotation processing tool
25. Retention
public enum RetentionPolicy {
/* only exist before compile finish. */
SOURCE,
/* recorded in the class file by the compiler but need not
be retained by the VM at run time. */
CLASS,
/* to be recorded in the class file and can be used at run
time, so they may be read reflectively. */
RUNTIME
}
26. Retention
public enum RetentionPolicy {
/* only exist before compile finish. */
SOURCE,
/* recorded in the class file by the compiler but need not
be retained by the VM at run time. */
CLASS,
/* to be recorded in the class file and can be used at run
time, so they may be read reflectively. */
RUNTIME
}
27. Retention
public enum RetentionPolicy {
/* only exist before compile finish. */
SOURCE,
/* recorded in the class file by the compiler but need not
be retained by the VM at run time. */
CLASS,
/* to be recorded in the class file and can be used at run
time, so they may be read reflectively. */
RUNTIME
}
28. Retention
public enum RetentionPolicy {
/* only exist before compile finish. */
SOURCE,
/* recorded in the class file by the compiler but need not
be retained by the VM at run time. */
CLASS,
/* to be recorded in the class file and can be used at run
time, so they may be read reflectively. */
RUNTIME
}
29. Processor module
Only used in compile phase.
Not include in final Jar/Apk.
Can contain several Processors.
32. public interface Processor {
/** Initializes with the processing environment. */
void init(ProcessingEnvironment processingEnv);
/** Returns the target the annotation types to process. */
Set<String> getSupportedAnnotationTypes();
/** Processes a set of annotation on type elements. */
boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv);
…
}
Processor
33. public interface Processor {
/** Initializes with the processing environment. */
void init(ProcessingEnvironment processingEnv);
/** Returns the target the annotation types to process. */
Set<String> getSupportedAnnotationTypes();
/** Processes a set of annotation on type elements. */
boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv);
…
}
Processor
34. public interface Processor {
/** Initializes with the processing environment. */
void init(ProcessingEnvironment processingEnv);
/** Returns the target the annotation types to process. */
Set<String> getSupportedAnnotationTypes();
/** Processes a set of annotation on type elements. */
boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv);
…
}
Processor
35. public interface Processor {
/** Initializes with the processing environment. */
void init(ProcessingEnvironment processingEnv);
/** Returns the target the annotation types to process. */
Set<String> getSupportedAnnotationTypes();
/** Processes a set of annotation on type elements. */
boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv);
…
}
Processor
36. Element
Unit of code element.
- PackageElement: Package
- TypeElement: Class, Interface
- ExecutableElement: Method, Constructor
37. @Override
public boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv) {
for (Element element :
roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
if (element.getKind() != ElementKind.INTERFACE) {
error("Only interface can be used with MyAnnotation", element);
return true;
}
TypeElement typeElement = (TypeElement) element;
typeElement.getInterfaces();
typeElement.getSuperclass();
typeElement.getSimpleName();
MyAnnotation anno = element.getAnnotation(MyAnnotation.class);
/** Custom logic to build the relation graph and generate the file*/
}
return true;
}
38. @Override
public boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv) {
for (Element element :
roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
if (element.getKind() != ElementKind.INTERFACE) {
error("Only interface can be used with MyAnnotation", element);
return true;
}
TypeElement typeElement = (TypeElement) element;
typeElement.getInterfaces();
typeElement.getSuperclass();
typeElement.getSimpleName();
MyAnnotation anno = element.getAnnotation(MyAnnotation.class);
/** Custom logic to build the relation graph and generate the file*/
}
return true;
}
39. @Override
public boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv) {
for (Element element :
roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
if (element.getKind() != ElementKind.INTERFACE) {
error("Only interface can be used with MyAnnotation", element);
return true;
}
TypeElement typeElement = (TypeElement) element;
typeElement.getInterfaces();
typeElement.getSuperclass();
typeElement.getSimpleName();
MyAnnotation anno = element.getAnnotation(MyAnnotation.class);
/** Custom logic to build the relation graph and generate the file*/
}
return true;
}
40. @Override
public boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv) {
for (Element element :
roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
if (element.getKind() != ElementKind.INTERFACE) {
error("Only interface can be used with MyAnnotation", element);
return true;
}
TypeElement typeElement = (TypeElement) element;
typeElement.getInterfaces();
typeElement.getSuperclass();
typeElement.getSimpleName();
MyAnnotation anno = element.getAnnotation(MyAnnotation.class);
/** Custom logic to build the relation graph and generate the file*/
}
return true;
}
41. @Override
public boolean process(Set<? extends TypeElement> set,
RoundEnvironment roundEnv) {
for (Element element :
roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
if (element.getKind() != ElementKind.INTERFACE) {
error("Only interface can be used with MyAnnotation", element);
return true;
}
TypeElement typeElement = (TypeElement) element;
typeElement.getInterfaces();
typeElement.getSuperclass();
typeElement.getSimpleName();
MyAnnotation anno = element.getAnnotation(MyAnnotation.class);
/** Custom logic to build the relation graph and generate the file*/
}
return true;
}
52. TypeSpec helloWorld = TypeSpec.classBuilder("HellowWorld")
.addMethod(MethodSpec.{…})
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.build();
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
JavaPoet
53. Tips
Find the boilerplate of daily work, eg: findViewById,
dependency graph, deep link, etc.
Find the pattern and define each component.
Label each component with annotation.
Create processor to generate code and link each
component.
55. Factory
public interface Animal {}
public class Cat implements Animal {}
public class Dog implements Animal {}
public final class AnimalFactory {
public static Animal createAnimal(String type) {
switch(type) {
case "cat": return new Cat();
case "dog": return new Dog();
}
throw new RuntimeException("not support type");
}
}
56. Factory
public interface Animal {}
public class Cat implements Animal {}
public class Dog implements Animal {}
public final class AnimalFactory {
public static Animal createAnimal(String type) {
switch(type) {
case "cat": return new Cat();
case "dog": return new Dog();
}
throw new RuntimeException("not support type");
}
}
57. Auto Generate?
@AutoFactory
public interface Animal {}
@AutoElement(AnimalTags.CAT)
public class Cat implements Animal {}
@AutoElement(AnimalTags.DOG)
public class Dog implements Animal {}
// https://github.com/Jintin/AutoFactory
59. 1 ViewHolder
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}
60. Add ViewHolder
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
protected static final int TYPE_HOLDER2 = 2;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
case TYPE_HOLDER2: {
return new Holder2(LayoutInflater.from(context).inflate(R.layout.view2, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}
61. Add more ViewHolder
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
protected static final int TYPE_HOLDER2 = 2;
protected static final int TYPE_HOLDER3 = 3;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
case TYPE_HOLDER2: {
return new Holder2(LayoutInflater.from(context).inflate(R.layout.view2, parent, false));
}
case TYPE_HOLDER3: {
return new Holder3(LayoutInflater.from(context).inflate(R.layout.view3, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}
62. Even more ViewHolders
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
protected static final int TYPE_HOLDER2 = 2;
protected static final int TYPE_HOLDER3 = 3;
protected static final int TYPE_HOLDER4 = 4;
protected static final int TYPE_HOLDER5 = 5;
protected static final int TYPE_HOLDER6 = 6;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
case TYPE_HOLDER2: {
return new Holder2(LayoutInflater.from(context).inflate(R.layout.view2, parent, false));
}
case TYPE_HOLDER3: {
return new Holder3(LayoutInflater.from(context).inflate(R.layout.view3, parent, false));
}
case TYPE_HOLDER4: {
return new Holder4(LayoutInflater.from(context).inflate(R.layout.view4, parent, false));
}
case TYPE_HOLDER5: {
return new Holder5(LayoutInflater.from(context).inflate(R.layout.view5, parent, false));
}
case TYPE_HOLDER6: {
return new Holder6(LayoutInflater.from(context).inflate(R.layout.view6, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}
63. Even more Adapters
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
protected static final int TYPE_HOLDER2 = 2;
protected static final int TYPE_HOLDER3 = 3;
protected static final int TYPE_HOLDER4 = 4;
protected static final int TYPE_HOLDER5 = 5;
protected static final int TYPE_HOLDER6 = 6;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
case TYPE_HOLDER2: {
return new Holder2(LayoutInflater.from(context).inflate(R.layout.view2, parent, false));
}
case TYPE_HOLDER3: {
return new Holder3(LayoutInflater.from(context).inflate(R.layout.view3, parent, false));
}
case TYPE_HOLDER4: {
return new Holder4(LayoutInflater.from(context).inflate(R.layout.view4, parent, false));
}
case TYPE_HOLDER5: {
return new Holder5(LayoutInflater.from(context).inflate(R.layout.view5, parent, false));
}
case TYPE_HOLDER6: {
return new Holder6(LayoutInflater.from(context).inflate(R.layout.view6, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected static final int TYPE_HOLDER1 = 1;
protected static final int TYPE_HOLDER2 = 2;
protected static final int TYPE_HOLDER3 = 3;
protected static final int TYPE_HOLDER4 = 4;
protected static final int TYPE_HOLDER5 = 5;
protected static final int TYPE_HOLDER6 = 6;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HOLDER1: {
return new Holder1(LayoutInflater.from(context).inflate(R.layout.view1, parent, false));
}
case TYPE_HOLDER2: {
return new Holder2(LayoutInflater.from(context).inflate(R.layout.view2, parent, false));
}
case TYPE_HOLDER3: {
return new Holder3(LayoutInflater.from(context).inflate(R.layout.view3, parent, false));
}
case TYPE_HOLDER4: {
return new Holder4(LayoutInflater.from(context).inflate(R.layout.view4, parent, false));
}
case TYPE_HOLDER5: {
return new Holder5(LayoutInflater.from(context).inflate(R.layout.view5, parent, false));
}
case TYPE_HOLDER6: {
return new Holder6(LayoutInflater.from(context).inflate(R.layout.view6, parent, false));
}
default: throw new RuntimeException("Not support type" + viewType);
}
}
}