有多简单,仅仅只有跳转功能,主要为了了解AbstractProcessor的使用
是什么
也就是常说的APT,和aapt不一样啊,不一样的东西。
是一个在javac中的,用来编译时扫描和处理的注解的工具。你可以为特定的注解,注册你自己的注解处理器。
干嘛用
比如各种路由框架,黄油刀什么的都会使用到 apt,为什么要用呢,还是为了能够生成代码,有些代码不用使用者去使用,比较方便
怎么用
先说流程,先依赖,然后需要写一个注解,一般都是根据注解来处理,其次继承AbstractProcessor,在process函数中,生成自己需要的类。
依赖
implementation 'com.google.auto.service:auto-service:1.0-rc6'annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'implementation 'com.squareup:javapoet:1.10.0'compileOnly files(Jvm.current().getToolsJar())
写个注解
@Target(ElementType.TYPE)@Retention(RetentionPolicy.CLASS)public @interface Router {String path();}
继承AbstractProcessor
@AutoService(Processor.class)@SupportedAnnotationTypes("net.mikaelzero.interfaces.Router")@SupportedSourceVersion(SourceVersion.RELEASE_8)public class UriProcessor extends BaseProcessor {@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {super.process(annotations, roundEnv);.......return true;}}
BaseProcessor是啥,直接copy WMRouter的
两个注意点,注解写在单独的module中,比如叫interfaces,处理AbstractProcessor的也写在一个单独的module中,比如叫complie,这两个都是java工程,不是android工程。
生成java文件
@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {super.process(annotations, roundEnv);if (annotations == null || annotations.isEmpty()) {return false;}CodeBlock.Builder builder = CodeBlock.builder();for (Element element : roundEnv.getElementsAnnotatedWith(Router.class)) {if (!(element instanceof Symbol.ClassSymbol)) {continue;}boolean isActivity = isActivity(element);if (!isActivity) {continue;}Symbol.ClassSymbol cls = (Symbol.ClassSymbol) element;Router uri = cls.getAnnotation(Router.class);if (uri == null) {continue;}CodeBlock handler = buildHandler(isActivity, cls);String path = uri.path();builder.addStatement("handler.register($S, $L)", path, handler);}//由于随机生成类名,需要根据接口去找对应实现类,代码量较多,作为演示,取一个固定的名字buildHandlerInitClass(builder.build(), "UriAnnotationInitImpl", Const.URI_ANNOTATION_HANDLER_CLASS, Const.URI_ANNOTATION_INIT_CLASS);return true;}
点击小锤子编译后,看看生成的文件,文件在你使用annotationProcessor compile的module中的generated中
public class UriAnnotationInitImpl implements IUriAnnotationInit {public void init(UriHandler handler) {handler.register("/second", "net.mikaelzero.second.SecondActivity");}}
IUriAnnotationInit是个啥,虽然我们编写好了生成代码的策略,但是这个生成好的代码,该怎么运行?
没错,用一个接口,在通过开放一个函数(比如init什么的),在init中,对所有实现了该接口的实现类进行实例化并且调用。
最后一步
调用上面的init函数,为了追求简单,我直接在生成类的时候生成为固定的名字,然后实例化并调用init
void init() {try {Class<?> clazz = Class.forName("net.mikaelzero.router.generated.UriAnnotationInitImpl");IUriAnnotationInit annotationInit = (IUriAnnotationInit) clazz.newInstance();annotationInit.init(new UriHandler());} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();}}
再看看UriHandler
public class UriHandler {private static final Map<String, String> mMap = new HashMap<>();public void register(String path, String handler) {String pathHandler = mMap.get(path);if (pathHandler == null) {mMap.put(path, handler);}}public static Intent createIntent(Context context, @NonNull String path) {return new Intent().setClassName(context, mMap.get(path));}}
同样追求简单,直接写成了static,最后就是调用,并跳转了.
@Router(path = "/second")public class SecondActivity extends AppCompatActivity {......}startActivity(UriHandler.createIntent(this, "/second"));
总结
看起来好像和gradle没啥关系啊,但是gradle和asm有关系,javapoet和asm有关系
