美文网首页
注解处理器

注解处理器

作者: Android_小马范儿 | 来源:发表于2019-04-24 14:08 被阅读0次

    平时大家用的注解都是运行时通过反射机制运行处理|的注解,本篇文章讨论的是编译时处理的注解,一般用来自动生成代码的注解例如ButterKnife;
    如果需要使用注解处理器,引用时使用代码如下(以butterknife举例):

     implementation 'com.jakewharton:butterknife:8.5.1'
    //引用注解处理器,在编译是自动生成相关代码
     annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    
    使用ButterKnife的主代码
    public class ScrollingActivity extends AppCompatActivity {
    
        private static final String TAG = "ScrollingActivity";
        @BindView(R.id.btn_bk)
        Button mBtnBk;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_scrolling);
            ButterKnife.bind(this);
        }
    
        private void annotationStartActivity() {
            RouterService routerService = new Router(this).create(RouterService.class);
            User user = new User("张三来了", 300);
            routerService.startLibraryActivity("xiaoma", user);
        }
    
        @OnClick(R.id.btn_bk)
        public void onClick(View v) {
            switch (v.getId()) {
                default:
                    break;
                case R.id.btn_bk:
                   annotationStartActivity();
                    break;
            }
        }
    }
    
    编译后自动生成了ScrollingActivity_ViewBinding类,而 ButterKnife.bind(this)相当于初始化了这个类,如果去掉 ButterKnife.bind(this),改成new ScrollingActivity_ViewBinding(this)是跟上面的代码功能一致的;该类代码如下:
    public class ScrollingActivity_ViewBinding implements Unbinder {
      private ScrollingActivity target;
    
      private View view2131230756;
    
      @UiThread
      public ScrollingActivity_ViewBinding(ScrollingActivity target) {
        this(target, target.getWindow().getDecorView());
      }
    
      @UiThread
      public ScrollingActivity_ViewBinding(final ScrollingActivity target, View source) {
        this.target = target;
    
        View view;
        view = Utils.findRequiredView(source, R.id.btn_bk, "field 'mBtnBk' and method 'onClick'");
        target.mBtnBk = Utils.castView(view, R.id.btn_bk, "field 'mBtnBk'", Button.class);
        view2131230756 = view;
        view.setOnClickListener(new DebouncingOnClickListener() {
          @Override
          public void doClick(View p0) {
            target.onClick(p0);
          }
        });
      }
    
      @Override
      @CallSuper
      public void unbind() {
        ScrollingActivity target = this.target;
        if (target == null) throw new IllegalStateException("Bindings already cleared.");
        this.target = null;
    
        target.mBtnBk = null;
    
        view2131230756.setOnClickListener(null);
        view2131230756 = null;
      }
    

    下面说下注解处理器

    1. 虚处理器AbstractProcessor
      注解处理器的入口就是继承了AbstractProcessor的继承类的process方法
    @AutoService(Processor.class)
    public class InjectProcessor extends AbstractProcessor {
       
       private Types mTypeUtils;
        private Filer mFiler;
        private Messager mMessages;
        private Elements mElementUtils;
    
        @Override
        public synchronized void init(ProcessingEnvironment env){
            /* Element代表程序的元素,例如包、类和方法*/
            mElementUtils = processingEnv.getElementUtils();
            /*处理TypeMirror的工具类,用于取类信息*/
            mTypeUtils = processingEnv.getTypeUtils();
            /* File可以创建文件*/
            mFiler = processingEnv.getFiler();
            mMessages = processingEnv.getMessager();
     }
    
        @Override
        public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }
    
        @Override
        public Set<String> getSupportedAnnotationTypes() { }
    
        @Override
        public SourceVersion getSupportedSourceVersion() { }
    
    }
    
    • init(ProcessingEnvironment env)方法用来提供核心的四个参数分别是Elements、Types、Filer、Messager
    • process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)核心入口
    • getSupportedAnnotationTypes() 必须指定这个注解处理器是注册给那个注解的,注意返回的是一个字符串的集合,也就是改注解处理器处理你指定的注解结合
    • getSupportedSourceVersion() 用来指定你使用的java版本;建议直接使用SourceVersion.latestSupported()返回
    1. 注册你的处理器
      怎么把处理器InjectProcessor注册到javac中,通过google提供的auto-service引用到项目中,并且把@AutoService(Processor.class)放到类InjectProcessor 上面就可以
    apply plugin: 'java-library'
    
    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
        implementation 'com.squareup:javapoet:1.8.0'
        implementation 'com.google.auto.service:auto-service:1.0-rc5'
        implementation project(':processor')
    }
    
    sourceCompatibility = "7"
    targetCompatibility = "7"
    
    1. 抛出问题处理
      如果你在process()中抛出一个异常,那么运行注解处理器的JVM将会崩溃(就像其他Java应用一样),使用我们注解处理器FactoryProcessor第三方开发者将会从javac中得到非常难懂的出错信息,因为它包含FactoryProcessor的堆栈跟踪(Stacktace)信息。因此,注解处理器就有一个Messager类,它能够打印非常优美的错误信息,并且return true,退出处理
    2. 自动生成代码,也是注解处理器的关键内容,这样生成的新类就可以直接使用,建议使用如下引用库生成java代码
    implementation 'com.squareup:javapoet:1.8.0'
    

    相关内容可以搜索javapoet相关内容

    1. 分离注解处理器和注解
      这样处理器相关的代码就无序引用到项目内了,只把对应的注解引入就ok

    关于路由和注解的项目地址
    参考文章: 注解处理器

    相关文章

      网友评论

          本文标题:注解处理器

          本文链接:https://www.haomeiwen.com/subject/zyewgqtx.html