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