[关闭]
@yudesong 2017-04-06T15:08:47.000000Z 字数 7952 阅读 630

ButterKnife源码分析

Android ButterKnife


  1. /**
  2. * Created by Zeno on 2016/10/22.
  3. *
  4. * 辅助类的父接口 , T 代表注入的目标类型,ViewInject注入目标为Activity
  5. */
  6. public interface IVInjectorAdapter<T> {
  7. void injects(T target);
  8. }
  1. /**
  2. * Created by Zeno on 2016/10/21.
  3. *
  4. * View inject
  5. * 字段注入注解,可以新建多个注解,再通过AnnotationProcessor进行注解处理
  6. * RetentionPolicy.CLASS ,在编译的时候进行注解 。我们需要在生成.class文件的时候需要进行处理
  7. */
  8. @Retention(RetentionPolicy.CLASS)
  9. @Target(ElementType.FIELD)
  10. public @interface VInjector {
  11. int value();
  12. }
  1. /**
  2. * Created by Zeno on 2016/10/21.
  3. *
  4. * Inject in View annotation processor
  5. *
  6. * 需要在配置文件中指定处理类 resources/META-INF/services/javax.annotation.processing.Processor
  7. * com.zeno.viewinject.apt.VInjectProcessor
  8. */
  9. @SupportedAnnotationTypes("com.zeno.viewinject.annotation.VInjector")
  10. @SupportedSourceVersion(SourceVersion.RELEASE_6)
  11. public class VInjectProcessor extends AbstractProcessor {
  12. List<IAnnotationHandler> mAnnotationHandler = new ArrayList<>();
  13. Map<String,List<VariableElement>> mHandleAnnotationMap = new HashMap<>();
  14. private IGenerateAdapter mGenerateAdapter;
  15. @Override
  16. public synchronized void init(ProcessingEnvironment processingEnv) {
  17. super.init(processingEnv);
  18. // init annotation handler , add handler
  19. registerHandler(new VInjectHandler());
  20. // init generate adapter
  21. mGenerateAdapter = new ViewGenerateAdapter(processingEnv);
  22. }
  23. /*可以有多个处理*/
  24. protected void registerHandler(IAnnotationHandler handler) {
  25. mAnnotationHandler.add(handler);
  26. }
  27. // annotation into process run
  28. @Override
  29. public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  30. for (IAnnotationHandler handler : mAnnotationHandler) {
  31. // attach environment , 关联环境
  32. handler.attachProcessingEnvironment(processingEnv);
  33. // handle annotation 处理注解 ,得到注解类的属性列表
  34. mHandleAnnotationMap.putAll(handler.handleAnnotation(roundEnv));
  35. }
  36. // 生成辅助类
  37. mGenerateAdapter.generate(mHandleAnnotationMap);
  38. // 表示处理
  39. return true;
  40. }
  41. }
  1. public abstract class AbstractGenerateAdapter implements IGenerateAdapter {
  2. private ProcessingEnvironment processingEnvironment;
  3. private final Filer mFiler;
  4. public AbstractGenerateAdapter(ProcessingEnvironment processingEnvironment) {
  5. this.processingEnvironment = processingEnvironment;
  6. mFiler = processingEnvironment.getFiler();
  7. }
  8. /**
  9. * 模版方法 : 确定算法的框架 ,将算法的实现推迟到子类里面
  10. * @param map
  11. */
  12. @Override
  13. public void generate(Map<String, List<VariableElement>> map) {
  14. Set<Map.Entry<String, List<VariableElement>>> entries = map.entrySet();
  15. Iterator<Map.Entry<String, List<VariableElement>>> iterator = entries.iterator();
  16. PrintUtils.print("size === "+entries.size());
  17. // 遍历出注入的属性集合
  18. while (iterator.hasNext()){
  19. Map.Entry<String, List<VariableElement>> entry = iterator.next();
  20. List<VariableElement> elementList = entry.getValue();
  21. if (elementList == null || elementList.isEmpty()) {
  22. continue;
  23. }
  24. InjectInfo injectInfo = createInjectInfo(elementList.get(0));
  25. /*创建一个Java源文件*/
  26. Writer writer = null;
  27. try {
  28. JavaFileObject javaFileObject = mFiler.createSourceFile(injectInfo.getFullClassName());
  29. writer = javaFileObject.openWriter();
  30. /*头部*/
  31. generateImport(writer,injectInfo);
  32. /*属性部分*/
  33. for(VariableElement element : elementList) {
  34. generateField(writer,element,injectInfo);
  35. }
  36. PrintUtils.print("\n\n what is one ?....\n\n");
  37. /*尾部*/
  38. generateFooter(writer);
  39. } catch (IOException e) {
  40. e.printStackTrace();
  41. }finally {
  42. if (writer != null) {
  43. try {
  44. writer.close();
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. }
  50. }
  51. }
  52. /**
  53. * 创建一个InjectInfo对象
  54. * @param variableElement
  55. * @return
  56. */
  57. private InjectInfo createInjectInfo(VariableElement variableElement) {
  58. TypeElement typeElement = (TypeElement) variableElement.getEnclosingElement();
  59. String className = typeElement.getSimpleName().toString();
  60. String packageName = AnnotationUtils.getPackageName(processingEnvironment, typeElement);
  61. return new InjectInfo(packageName,className);
  62. }
  63. /**
  64. * 生成import 头部
  65. * @param writer
  66. */
  67. protected abstract void generateImport(Writer writer,InjectInfo injectInfo) throws IOException;
  68. /**
  69. * 生成类字段
  70. * @param writer
  71. */
  72. protected abstract void generateField(Writer writer,VariableElement variableElement,InjectInfo injectInfo) throws IOException;
  73. /**
  74. * 生成尾部
  75. * @param writer
  76. */
  77. protected abstract void generateFooter(Writer writer) throws IOException;
  78. /**
  79. * 注入信息
  80. */
  81. class InjectInfo{
  82. public String packageName;
  83. public String className;
  84. public String newClassName;
  85. public InjectInfo(String packageName, String className) {
  86. this.packageName = packageName;
  87. this.className = className;
  88. this.newClassName = className+ ViewInject.SUFFIX;
  89. }
  90. /**
  91. * 辅助类的完整类名
  92. * @return string className
  93. */
  94. public String getFullClassName(){
  95. return packageName+"."+newClassName;
  96. }
  97. }
  98. }
  1. public interface IGenerateAdapter {
  2. /**
  3. * 根据解析注解的内容生成辅助类
  4. * @param map
  5. */
  6. void generate(Map<String,List<VariableElement>> map);
  7. }
  1. public class ViewGenerateAdapter extends AbstractGenerateAdapter {
  2. public ViewGenerateAdapter(ProcessingEnvironment processingEnvironment) {
  3. super(processingEnvironment);
  4. }
  5. @Override
  6. protected void generateImport(Writer writer, InjectInfo injectInfo) throws IOException {
  7. writer.write("package "+injectInfo.packageName+";");
  8. writer.write("\n\n");
  9. writer.write("import com.zeno.viewinject.adapter.IVInjectorAdapter;");
  10. writer.write("\n\n");
  11. writer.write("import com.zeno.viewinject.utils.ViewFinder;");
  12. writer.write("\n\n\n");
  13. writer.write("/* This class file is generated by ViewInject , do not modify */");
  14. writer.write("\n");
  15. writer.write("public class "+injectInfo.newClassName+" implements IVInjectorAdapter<"+injectInfo.className+"> {");
  16. writer.write("\n\n");
  17. writer.write("public void injects("+injectInfo.className+" target) {");
  18. writer.write("\n");
  19. }
  20. @Override
  21. protected void generateField(Writer writer, VariableElement variableElement, InjectInfo injectInfo) throws IOException {
  22. VInjector vInjector = variableElement.getAnnotation(VInjector.class);
  23. int resId = vInjector.value();
  24. String fieldName = variableElement.getSimpleName().toString();
  25. writer.write("\t\ttarget."+fieldName+" = ViewFinder.findViewById(target,"+resId+");");
  26. writer.write("\n");
  27. }
  28. @Override
  29. protected void generateFooter(Writer writer) throws IOException {
  30. writer.write(" \t}");
  31. writer.write("\n\n");
  32. writer.write("}");
  33. }
  34. }
  1. public interface IAnnotationHandler {
  2. /**
  3. * attch environment
  4. * @param environment 处理环境
  5. */
  6. void attachProcessingEnvironment(ProcessingEnvironment environment) ;
  7. /**
  8. * handle annotation 处理注解 ,生成辅助类的时候需要用到注解的类型
  9. * @param roundEnvironment 周边环境
  10. * @return <p>
  11. * Map<String,List<VariableElement>>
  12. * key ---> 表示是哪个类的注入 (宿主)
  13. * value ---> 表示注解类的注入的字段属性列表 (注解字段)
  14. * </p>
  15. */
  16. Map<java.lang.String, List<VariableElement>> handleAnnotation(RoundEnvironment roundEnvironment);
  17. }
  1. public class VInjectHandler implements IAnnotationHandler {
  2. private ProcessingEnvironment mProcessingEnvironment;
  3. @Override
  4. public void attachProcessingEnvironment(ProcessingEnvironment environment) {
  5. this.mProcessingEnvironment = environment;
  6. }
  7. @Override
  8. public Map<String, List<VariableElement>> handleAnnotation(RoundEnvironment roundEnvironment) {
  9. Map<String,List<VariableElement>> map = new HashMap<>();
  10. /*获取一个类中带有VInjector注解的属性列表*/
  11. Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(VInjector.class);
  12. for (Element element : elements) {
  13. VariableElement variableElement = (VariableElement) element;
  14. /*获取类名 ,将类目与属性配对,一个类,对于他的属性列表*/
  15. String className = getFullClassName(variableElement);
  16. List<VariableElement> cacheElements = map.get(className);
  17. if (cacheElements == null) {
  18. cacheElements = new ArrayList<>();
  19. map.put(className,cacheElements);
  20. }
  21. cacheElements.add(variableElement);
  22. }
  23. return map;
  24. }
  25. /**
  26. * 获取注解属性的完整类名
  27. * @param variableElement
  28. */
  29. private String getFullClassName(VariableElement variableElement) {
  30. TypeElement typeElement = (TypeElement) variableElement.getEnclosingElement();
  31. String packageName = AnnotationUtils.getPackageName(mProcessingEnvironment,typeElement);
  32. return packageName+"."+typeElement.getSimpleName().toString();
  33. }
  34. }
  1. public class ViewInject {
  2. public static final String SUFFIX = "$VInjectorAdapter";
  3. static Map<Class<? extends Activity>,IVInjectorAdapter<?>> mInjectorAdapter = new HashMap();
  4. public static void inject(Activity activity) {
  5. IVInjectorAdapter<Object> vInjectorAdapter = getVInjectorAdapter(activity.getClass());
  6. vInjectorAdapter.injects(activity);
  7. }
  8. private static <T>IVInjectorAdapter<T> getVInjectorAdapter(Class<? extends Activity> clazz){
  9. IVInjectorAdapter<T> injectorAdapter = (IVInjectorAdapter<T>) mInjectorAdapter.get(clazz);
  10. if (injectorAdapter != null){
  11. return injectorAdapter;
  12. }
  13. String adapterClassName = clazz.getName()+SUFFIX;
  14. try{
  15. injectorAdapter = (IVInjectorAdapter<T>) Class.forName(adapterClassName).newInstance();
  16. mInjectorAdapter.put(clazz,injectorAdapter);
  17. }catch (Exception e){
  18. e.printStackTrace();
  19. }
  20. return injectorAdapter;
  21. }
  22. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注