ButterKnife源码分析二

    上一篇我对butterknife 的原理,做了一个分析。但是留了一个坑儿。就是xxx_viewbingding 是如何生成的。我们在使用butterknife 的时候 肯定会在gradle 中配置他的

 apt 'com.jakewharton:butterknife-compiler:8.4.0'
apt ,这个apt 是干什么用的不知道大家了不了解。简单来说这个apt 是一个插件,他有两个作用

1.可以在编译时使用注解处理器工作,但是在我们项目打包成apk时不会包含这些无用文件(因为编译时的注解处理器只在编译时有用,所以打包后这些文件是无用的)

2.可以辅助处理,注解处理器在编译时期生成的文件

说完了这些其实我主要想说的是这个butterknife-compiler 就是一个注解处理器库项目。所以文件生成肯定是在这个项目里实现的。说到这我想说说关于注解处理器的

一些小知识,我们要想让注解处理器可以使用,有几种方法配置 

第一种 在Meta-Info 文件夹下配置

META_INF/services/javax.annotation.processing ,  javax.annotation.processing  这个文件里面写上注解处理器是的类全路径名。经过研究 butter-knife 使用了这一种。

butterknife.compiler.ButterKnifeProcessor
第二种 直接在追截处理器 的类上使用autoservce 注解 。 经过研究butter-kinfe 也使用了这种

@AutoService(Processor.class)
public final class ButterKnifeProcessor extends AbstractProcessor {

第三种就是我们的apt  

所以说 我们butter-knife 这三种都用了。那么其实不知道他为啥要这么做。我们知道apt 是最有优势的就行了。然后我们查看这个butterknifeprocessor 类 开始还是要

 说下注解处理器的一些基本知识 。

注解处理器一般都是继承于abstractprocessor  并且实现他的几个方法

public class TestProcessor extends AbstractProcessor {  
  
    @Override  
    public synchronized void init(ProcessingEnvironment processingEnv) {  
        super.init(processingEnv);  
    }  
  
    
     //annotations   请求处理的注解类型 
     //roundEnv  有关当前和以前的信息环境 
      //这个方法里就是处理注解的地方。也就是生成xxx_viewbinding   的地方
    @Override  
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {  
        return false;  
    }  
  
     
    @Override  
    public Set<String> getSupportedAnnotationTypes() {  
        Set<String> annotataionset = new LinkedHashSet<String>();  
        annotataionset.add(Anotations.class.getCanonicalName());  //这里获取到的注解处理器支持的类型集合。 
        return annotataions;   
    }  
  
   
     
 
    @Override  
    public SourceVersion getSupportedSourceVersion() {  
        return SourceVersion.latestSupported();  //使用的Java版本 
 } }

上面简单介绍了下 注解处理器下面看源码 直接看他的process 方法


@Override public boolean process(Set<? extends TypeElement> elements, RoundEnvironment env) {
    Map<TypeElement, BindingClass> targetClassMap = findAndParseTargets(env); 

    for (Map.Entry<TypeElement, BindingClass> entry : targetClassMap.entrySet()) {
      TypeElement typeElement = entry.getKey();
      BindingClass bindingClass = entry.getValue();

      JavaFile javaFile = bindingClass.brewJava();
      try {
        javaFile.writeTo(filer);
      } catch (IOException e) {
        error(typeElement, "Unable to write binding for type %s: %s", typeElement, e.getMessage());
      }
    }

    return true;
  }

首先通过 findAndParseTargets 获取map集合 然后通过 这个集合遍历 拿到bindingClass  通过brewJava 方法 获取javaFile 对象 


JavaFile brewJava() {
    return JavaFile.builder(bindingClassName.packageName(), createBindingClass())
        .addFileComment("Generated code from Butter Knife. Do not modify!")
        .build();
  }

最后通过javafile.writeTo(filer) 生成我们的 java 文件 有兴趣的朋友可以详细看看map集合的生成和 java文件的生成细节。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值