Android开发Android开发经验谈Android技术知识

Apt+JavaPoet,简单分析流程

2019-09-14  本文已影响0人  space0o0

背景知识

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类,在编译期扫描和处理定义的注解

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.tv) TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...无关代码...
        ButterKnife.bind(this);
    }
}

原始的绑定操作就是:
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文件

使用反射的方式,通过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();
    }
}

总结

其实就三步曲:

相关知识点:

上一篇下一篇

猜你喜欢

热点阅读