O que é APT?
APT (Ferramenta de processamento de anotações)
É uma ferramenta de processamento de anotações. Detecta as anotações nos arquivos de código-fonte e produz automaticamente o código com base nas anotações. Se quiser que um processador de anotações personalizado funcione normalmente, deve processá-lo por meio da ferramenta APT. Também pode ser entendido que somente após a ferramenta APT ser declarada, o interpretador de anotação personalizado pode ser executado durante a compilação do programa.
Entendimento popular: de acordo com as regras, ajude-nos a gerar código e gerar arquivos de classe
Android Studio 3.4.1 + Gradle5.1.1 (versão recomendada)
Como usar o APT na componentização?
O desenvolvimento de componentes é para desacoplamento e alto isolamento. Cada módulo é independente. Se quisermos obter uma interação direta entre cada componente, podemos usar os seguintes métodos:
- A tecnologia de reflexão e reflexão pode ser bem-sucedida, o custo de manutenção é alto e a restrição @hide da versão alta tende a aparecer
- EvenTBus EventBean é muitos (um-para-um), um-para-muitos será confuso e difícil de manter (eu não tentei isso)
- O custo da manutenção implícita da intenção é bom, mas é mais problemático e requer muitas ações no Manifesto para ser mantido
- BroadCastReceiver requer registro dinâmico (após 7.0), e a parte necessitada envia uma transmissão
- O carregamento da classe requer um caminho preciso para o nome completo da classe, a manutenção da versão original é relativamente alta e está sujeita a erro humano
Então eu digo muito principalmente para dizer que APT é uma das melhores soluções para realizar a interação no desenvolvimento componentizado.
Então, como usar?
Primeiro, faça o salto de interface entre vários componentes como exemplo:
A interface salta entre o módulo da página principal (MainActivity) e o módulo de pedido (OrderActivity):
Um, crie uma nova classe de anotação
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)//RetentionPolicy.CLASS 编译期预编译的操作
public @interface ARouter {
//详细路由器路径(必填),如:"/app/MainActivity"
String path();
// 从path中截取出来
String group() default "";
}
2. Crie um novo ARouterProcessor para herdar AbstractProcessor para implementar o trabalho de anotação
ARouterProcessor herda AbstractProcessor, para a classe com a anotação ARouter, uma nova classe é gerada para uso interativo durante a compilação
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.goodboy.annotation.ARouter")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions("content")
public class ARouterProcessor extends AbstractProcessor {
//操作Element工具类
private Elements elementUtils;
//type(类信息)工具类
private Types typeUtils;
//用来输出警告,错误等日志
private Messager messager;
//文件生成器
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
elementUtils = processingEnvironment.getElementUtils();
typeUtils = processingEnvironment.getTypeUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
String content = processingEnvironment.getOptions().get("content");
messager.printMessage(Diagnostic.Kind.NOTE,content);
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (set.isEmpty())return false;
//获取项目中所有使用使用了ARouter注解的节点
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
//遍历所有的类节点
for (Element element : elements) {
//类节点之上,就是包节点
String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
//获取简单类名
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE,"被注解的类有:" + className);
// 最终我们想要生成的类文件 如:MainActivity$$ARouter
String finalClassName = className + "$$ARouter";
// 公开课写法,也是EventBus写法(https://github.com/greenrobot/EventBus)
try {
// 创建一个新的源文件(Class),并返回一个对象以允许写入它
JavaFileObject sourceFile = filer.createSourceFile(packageName + "." + finalClassName);
// 定义Writer对象,开启写入
Writer writer = sourceFile.openWriter();
// 设置包名
writer.write("package " + packageName + ";\n");
writer.write("public class " + finalClassName + " {\n");
writer.write("public static Class<?> findTargetClass(String path) {\n");
// 获取类之上@ARouter注解的path值
ARouter aRouter = element.getAnnotation(ARouter.class);
writer.write("if (path.equals(\"" + aRouter.path() + "\")) {\n");
writer.write("return " + className + ".class;\n}\n");
writer.write("return null;\n");
writer.write("}\n}");
// 最后结束别忘了
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
3. Adicione esta anotação às classes MainActivity e OrderActivity e use a classe gerada para pular para o
código MainActivity
@ARouter(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void jump(View view){
Class<?> targetClass = OrderActivity$$ARouter.findTargetClass("/app/OrderActivity");
startActivity(new Intent(this, targetClass));
}
}
Código OrderActivity
@ARouter(path = "/app/OrderActivity")
public class OrderActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
Log.d("mile", "--->OrderActivity");
}
public void jump(View view) {
Class<?> targetClass = MainActivity$$ARouter.findTargetClass("/app/MainActivity");
startActivity(new Intent(this, targetClass));
}
}
Resumo: O desenvolvimento de componentes é usar o APT dinamicamente para gerar classes interoperáveis