Componentes de los componentes de comunicaciones y APT, el uso JavaPoet (b)

directorio

  • La interacción entre los módulos
  • introducción y el uso de APT
  • APT de orden superior JavaPoet uso

La interacción entre los módulos

modo interactivo común

1) EventBus-uno de comunicaciones, objeto causa de la haba pandemia del
2) que refleja el mayor costo de la tecnología de mantenimiento, parece probable alta versión limitada a @hide
3) implícitos mayores costos de mantenimiento intención, la acción es más difícil de mantener
4) la necesidad de difusión dinámica 7,0 firmar
5) cargador de clases requiere la ruta completa de la clase

soluciones

el modo de carga de clases

Aquí Insertar imagen Descripción

public void jumpApp(View v){
    try {
        //通过全类名的方式进行跳转
        Class<?> clzz = Class.forName("com.canjun.myapplication.MainActivity");
        Intent intent = new Intent(this,clzz);
        startActivity(intent);
    }catch (Exception e){

    }
}
mapa global del modo de grabación

Aquí Insertar imagen Descripción

  1. Añadir una clase de récord mundial en un módulo común (módulo común)

     /**
      * RecorderPathManager
      * 记录全局的path信息
      *
      * @author zfc
      * @date 2020-01-09
      */
     public class RecorderPathManager {
     
         private static Map<String, List<PathBean>> paths = new HashMap<>();
     
         /**
          * 根据组名和路径名记录字节码信息
          * @param groupName
          * @param pathName
          * @param clazz
          */
         public static void joinGroup(String groupName,String pathName,Class clazz){
             List<PathBean> path = paths.get(groupName);
             if(path==null){
                 //添加
                 path = new ArrayList<>();
                 paths.put(groupName,path);
             }else {
                 for (PathBean p: path){
                     if(p.getPath().equals(pathName)){
                         return;
                     }
                 }
             }
             path.add(new PathBean(pathName,clazz));
         }
     
         /**
          * 获取目标字节码对象
          * @param groupName 组名
          * @param pathName 路径名
          * @return
          */
         public static Class getTargetClass(String groupName,String pathName){
             List<PathBean> path = paths.get(groupName);
             if(path==null){
                 return null;
             }
             for (PathBean p: path){
                 if(p.getPath().equals(pathName)){
                     return p.getClzz();
                 }
             }
     
             return null;
         }
     }
    
     /**
      * PathBean
      *
      * 记录Activity字节码及其路径
      * 例如
      *      path:'order/OrderMainActivity'
      *      clzz: OrderMainActivity.class
      *
      * @author zfc
      * @date 2020-01-09
      */
     public class PathBean {
     
         private String path;
     
         private Class clzz;
     
         public PathBean(String path, Class clzz) {
             this.path = path;
             this.clzz = clzz;
         }
     
         public String getPath() {
             return path;
         }
     
         public void setPath(String path) {
             this.path = path;
         }
     
         public Class getClzz() {
             return clzz;
         }
     
         public void setClzz(Class clzz) {
             this.clzz = clzz;
         }
     }
    
  2. Cuando se inicia la aplicación, las necesidades de objetos complemento de código de bytes que se registrarán

     /**
      * MyApp
      *
      * @author zfc
      * @date 2020-01-09
      */
     public class MyApp extends BaseApplication {
     
         @Override
         public void onCreate() {
             super.onCreate();
             //注册activity
             RecorderPathManager.joinGroup("app","MainActivity",MainActivity.class);
             RecorderPathManager.joinGroup("order","OrderMainActivity", OrderMainActivity.class);
             RecorderPathManager.joinGroup("personal","PersonalMainActivity", PersonalMainActivity.class);
         }
     }
    
  3. Cuando la página de destino del salto de código de bytes

      try {
         Class<?> clzz = RecorderPathManager.getTargetClass("app","MainActivity");
         Intent intent = new Intent(this, clzz);
         startActivity(intent);
     }catch (Exception e){
    
     }
    

introducción y el uso de APT

Lo que es APT

Aquí Insertar imagen Descripción

las estructuras del lenguaje

Clasificación elemento de lenguaje
Aquí Insertar imagen Descripción

Aquí Insertar imagen Descripción

API común

Aquí Insertar imagen Descripción

Aquí Insertar imagen Descripción

Uso básico APT

  1. Descripción del Medio Ambiente

    a. Crear una biblioteca de Java llamado compilador

    b. Añadir el compilador dependencia

      // 注册注解,并对其生成META-INF的配置信息,rc2在gradle5.0后有坑
     // As-3.2.1 + gradle4.10.1-all + auto-service:1.0-rc2
     // implementation 'com.google.auto.service:auto-service:1.0-rc2'
    
     // As-3.4.1 + gradle5.1.1-all + auto-service:1.0-rc4
     compileOnly'com.google.auto.service:auto-service:1.0-rc4'
     annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'
    
     implementation project(':annotation')
    
  2. La creación de procesador de anotación

     /*
      * 通过autoService通过生成文件
      */
     @AutoService(Processor.class)
     
     @SupportedAnnotationTypes({"com.canjun.annotation.ARouter"})
     @SupportedSourceVersion(SourceVersion.RELEASE_7)
     @SupportedOptions({"content"}) //外部传入的参数
     public class ARouterProcessor extends AbstractProcessor {
     
         /**
          * 操作Element的工具类
          */
         private Elements elementUtils;
     
         /**
          * 类信息工具类
          */
         private Types typesUtils;
     
         /**
          * 日志信息输出工具类
          */
         private Messager messager;
     
         /**
          * 文件生成器
          */
         private Filer filer;
     
         //初始化工作
         @Override
         public synchronized void init(ProcessingEnvironment processingEnv) {
             super.init(processingEnv);
             elementUtils = processingEnv.getElementUtils();
             typesUtils = processingEnv.getTypeUtils();
             messager = processingEnv.getMessager();
             filer = processingEnv.getFiler();
             
             //可以获取外部模块传入的参数
             //传参方式见下小结
             String content = processingEnv.getOptions().get("content");
             messager.printMessage(Diagnostic.Kind.NOTE,content);
         }
     //
     //    //需要处理的注解类型
     //    @Override
     //    public Set<String> getSupportedAnnotationTypes() {
     //        return super.getSupportedAnnotationTypes();
     //    }
     //
     //    //jdk版本去编辑
     //    @Override
     //    public SourceVersion getSupportedSourceVersion() {
     //        return super.getSupportedSourceVersion();
     //    }
     //
     //    //接收外部参数
     //    @Override
     //    public Set<String> getSupportedOptions() {
     //        return super.getSupportedOptions();
     //    }
     
         @Override
         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
     }
    
  3. Pasar parámetros a la biblioteca de Java compilador AndroidModule

     // 在gradle文件中配置选项参数值(用于APT传参接收)
     // 切记:必须写在defaultConfig节点下
      javaCompileOptions {
         annotationProcessorOptions {
             arguments = [content : 'hello apt']
         }
     }
    
  4. procesador anotación uso AndroidModule

    a.gradle comunicado la dependencia

      implementation project(':annotation')
     //使用注解处理器
     annotationProcessor project(':compiler')
    

    anotaciones uso b.Activity

     @ARouter(path="/app/MainActivity")
     public class MainActivity extends AppCompatActivity {
         ...
         ...
     }
    
  5. Implementación del método Notas de núcleo de procesamiento

     @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    
        if(annotations == null){
            return false;
        }
    
        messager.printMessage(Diagnostic.Kind.NOTE,annotations.toString());
    
        //获取被注解的类对象
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ARouter.class);
        for (Element e:elements){
            //获取包名
            String pkgName = elementUtils.getPackageOf(e).getQualifiedName().toString();
            //获取类名
            String className = e.getSimpleName().toString();
    
            messager.printMessage(Diagnostic.Kind.NOTE,pkgName + ">>" + className);
    
            //生成ARouter文件
            String finalClassName = className+"$$ARouter";
    
    
            try {
                JavaFileObject sourceFile =  filer.createSourceFile(pkgName+"."+finalClassName);
                Writer writer = sourceFile.openWriter();
                //设置包名
                writer.write("package "+pkgName + ";\n");
                writer.write("public class "+finalClassName+" {\n");
                writer.write("public static Class<?> findTargetClass(String pathName){\n");
                //获取注解的path的value(注意)
                String path = e.getAnnotation(ARouter.class).path();
                writer.write("if(pathName.equalsIgnoreCase(\""+path+"\")){\n");
                writer.write("return "+className+".class;\n");
                writer.write("}\n");
                writer.write("return null;\n");
                writer.write("}\n");
                writer.write("}\n");
                writer.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        return true;
    }
    
  6. procesador Verificación genera clase de anotación

    Por acumulación> Crear proyecto
    Aquí Insertar imagen Descripción

anotaciones AutoService utilizando el procesador de anotación generar la información de registro de localización en la siguiente figura.
Aquí Insertar imagen Descripción

el uso de APT y de orden superior JavaPoet

JavaPoet general

JavaPoet oficial a la dirección

Lo que es JavaPoet

Aquí Insertar imagen Descripción

entorno operativo JavaPoet

Aquí Insertar imagen Descripción

implementation 'com.squareup:javapoet:1.9.0'

// 注册注解,并对其生成META-INF的配置信息,rc2在gradle5.0后有坑
// As-3.2.1 + gradle4.10.1-all + auto-service:1.0-rc2
// implementation 'com.google.auto.service:auto-service:1.0-rc2'

// As-3.4.1 + gradle5.1.1-all + auto-service:1.0-rc4
compileOnly'com.google.auto.service:auto-service:1.0-rc4'
annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'
JavaPoet clase comúnmente usada

Aquí Insertar imagen Descripción

cadena de formato javaPoet

Aquí Insertar imagen Descripción

uso javaPoet

Código necesario para generar el siguiente formato
   package com.canjun.myapplication;
   public class MainActivity$$ARouter {

       public static Class findTargetClass(String name){
           if(name.equalsIgnoreCase("/app/MainActivity")){
               return MainActivity.class;
           }
           return null;
       }
    }
javaPoet escrito de la siguiente manera:
@AutoService(Processor.class)
@SupportedAnnotationTypes({"com.canjun.annotation.ARouter"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions({"content"})
public class ARouterProcessor extends AbstractProcessor {

    private Elements elementUtils;
    private Types typeUtils;
    private Messager messager;
    private Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        elementUtils = processingEnv.getElementUtils();
        typeUtils = processingEnv.getTypeUtils();
        messager = processingEnv.getMessager();
        filer = processingEnv.getFiler();
        Map<String, String> options = processingEnv.getOptions();
        String content = options.get("content");
        messager.printMessage(Diagnostic.Kind.NOTE, content);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
       if(annotations==null||annotations.isEmpty()){
           return false;
       }

       //获取被ARouter注解的类
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ARouter.class);

       for (Element e : elements){
           //获取e的包名
           String pkgName = elementUtils.getPackageOf(e).getQualifiedName().toString();
           //获取类名
           String className = e.getSimpleName().toString();

           String newFileName = className+"$$ARouter";
           //通过javaPoet写新生成的文件
           //javaPoet项目地址https://github.com/square/javapoet

           try {
               String pathName = e.getAnnotation(ARouter.class).path();
               MethodSpec methodSpec = MethodSpec.methodBuilder("findTargetClass")
                       .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                       .returns(Class.class)
                       .addParameter(String.class, "name")
                       //需要注意的是 语句中的参数 不需要显式添加“;”
                       .addStatement(" if(name.equalsIgnoreCase($S)){\n" +
                               "                       return $T.class;\n" +
                               "                   }\n" +
                               "                   return null", pathName, ClassName.get((TypeElement)e))
                       .build();

               TypeSpec typeSpec = TypeSpec.classBuilder(newFileName)
                       .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                       .addMethod(methodSpec)
                       .build();

               JavaFile javaFile = JavaFile.builder(pkgName,typeSpec)
                       .build();


               javaFile.writeTo(filer);
           } catch (IOException ex) {
               ex.printStackTrace();
           }
       }

        return true;
    }

}

Generar resultados:

lf7keU.png

lf7ZFJ.png

Publicado 98 artículos originales · ganado elogios 6 · Vistas a 20000 +

Supongo que te gusta

Origin blog.csdn.net/dirksmaller/article/details/103930756
Recomendado
Clasificación