Apt+JavaPoet,简单分析流程

作者: space0o0 | 来源:发表于2019-09-14 16:11 被阅读0次

背景知识

APT:Annotation Processing Tool(注解处理器)

在编译期,扫描和处理定义的注解,这些库如butterknife,dragger2,eventbus都应用了该技术。

Project结构和module的作用

app

android app,运行的app

annotation(java类型的module)

用于创建注解的module
例如:@Bind(R.id.tv)

processor(java类型的module)

在编译期间处理注解,同时会生成相应的java文件
以Butterknife为例,在build文件中,都能看到*$$ViewBinder.java文件,这里面的代码就是自动生成的

library(android类型的module)

作为app和processor生成文件的桥梁,起到沟通作用。
例如:ButterKnife.bind(activity)

主要思路(以ButterKnife为例)

创建可用的注解(自定义注解)

创建注解类文件,代码中体现:@Bind(R.id.tv)

使用processor类,在编译期扫描和处理定义的注解

  • 在编译时,processor类扫描所有带注解的对象(根据annotation的@Target,存在不同的Element);

  • 扫描过程中,记录所有的Element,以key:类 value:List<Element>的形式作为缓存。
    key存放的类,在butterknife中就是activity/fragment。
    value存放的数据集合,就是该类中使用注解的对象。
    在下面的代码中,key就是MainActivity,value就是存放textView的集合。

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv) TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...无关代码...
        ButterKnife.bind(this);
    }
}
  • 在拿到项目中所有的@Bind后,需要做的就是绑定控件的操作。

原始的绑定操作就是:
MainActivity.textView=MainActivity.findViewById(R.id.tv)

现在,我们需要创建一个类,让该类帮我们做重复的findViewById工作。
使用JavaFileObject或是JavaPoet生成我们需要的类,我们给这个类名再加个特殊字符:$$ViewBind,最后就变成了MainActivity$$ViewBind.java。

//MainActivity$$ViewBind.java文件
//这里都是使用JavaFileObject或JavaPoet生成的
public class MainActivity$$ViewBind implements IViewBind<MainActivity> {
    @Override
    public void bind(MainActivity target) {
        target.textView = target.findViewById(2131165326);
    }
}

library关联app和*$$ViewBind文件

  • 这里的代码很简单,首先思考一个问题,我们已知了$$ViewBind的文件路径,如何生成该类?

使用反射的方式,通过Class.forName(文件路径)方法拿到该类。

调用该类的bind方法绑定,$$ViewBind类执行绑定控件的操作。

public static void bind(Object object) {
    //获取apt生成的类
    try {
        Class<?> clazz = Class.forName(object.getClass().getName() + "$$ViewBind");
        //new apt生成的类($$ViewBind)
        IViewBind targetClass = (IViewBind) clazz.newInstance();
        //调用类的方法绑定($$ViewBind.bind方法)
        targetClass.bind(object);
    } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
        e.printStackTrace();
    }
}

总结

其实就三步曲:

  • 找到注解对象
  • 生成绑定对象的类
  • app中调用桥梁,传入activity绑定控件

相关知识点:

  • 反射
  • Processor的使用(继承AbstractProcessor)
  • JavaPoet
  • 接口的理解

相关文章

网友评论

    本文标题:Apt+JavaPoet,简单分析流程

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