美文网首页
Android注解笔记

Android注解笔记

作者: R7_Perfect | 来源:发表于2019-08-07 11:34 被阅读0次

    注解(Annotation)

    元注解

    @Target 表明我们注解可以出现的地方。是一个ElementType枚举

    类型 说明
    ElementType.TYPE 接口、类、枚举、注解
    ElementType.FIELD 字段、枚举的常量
    ElementType.METHOD 方法
    ElementType.PARAMETER 方法参数
    ElementType.CONSTRUCTOR 构造函数
    ElementType.LOCAL_VARIABLE 局部变量
    ElementType.ANNOTATION_TYPE 注解
    ElementType.PACKAGE

    @Retention 这个注解的的存活时间

    类型 说明
    RetentionPolicy.SOURCE 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
    RetentionPolicy.CLASS 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
    RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

    @Document 表明注解可以被javadoc此类的工具文档化
    @Inherited 是否允许子类继承该注解,默认为false

    反射相关

        /**
         * 包名加类名
         */
        public String getName();
        /**
         * 类名
         */
        public String getSimpleName();
        /**
         * 返回当前类和父类层次的public构造方法
         */
        public Constructor<?>[] getConstructors();
        /**
         * 返回当前类所有的构造方法(public、private和protected)
         * 不包括父类
         */
        public Constructor<?>[] getDeclaredConstructors();
        /**
         * 返回当前类所有public的字段,包括父类
         */
        public Field[] getFields();
        /**
         * 返回当前类所有申明的字段,即包括public、private和protected,
         * 不包括父类
         */
        public native Field[] getDeclaredFields();
        /**
         * 返回当前类所有public的方法,包括父类
         */
        public Method[] getMethods();
        /**
         * 返回当前类所有的方法,即包括public、private和protected,
         * 不包括父类
         */
        public Method[] getDeclaredMethods();
        /**
         * 获取局部或匿名内部类在定义时所在的方法
         */
        public Method getEnclosingMethod();
        /**
         * 获取当前类的包
         */
        public Package getPackage();
        /**
         * 获取当前类的包名
         */
        public String getPackageName$();
        /**
         * 获取当前类的直接超类的 Type
         */
        public Type getGenericSuperclass();
        /**
         * 返回当前类直接实现的接口.不包含泛型参数信息
         */
        public Class<?>[] getInterfaces();
        /**
         * 返回当前类的修饰符,public,private,protected
         */
        public int getModifiers();
    //==========================注解相关===========================================
        /**
         * 指定类型的注释是否存在于此元素上
         */
        default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
            return getAnnotation(annotationClass) != null;
        }
        /**
         * 返回该元素上存在的指定类型的注解
         */
        <T extends Annotation> T getAnnotation(Class<T> annotationClass);
        /**
         * 返回该元素上存在的所有注解
         */
        Annotation[] getAnnotations();
        /**
         * 返回该元素指定类型的注解
         */
        default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
            return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass);
        }
        /**
         * 返回直接存在与该元素上的所有注释(父类里面的不算)
         */
        default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
            Objects.requireNonNull(annotationClass);
            // Loop over all directly-present annotations looking for a matching one
            for (Annotation annotation : getDeclaredAnnotations()) {
                if (annotationClass.equals(annotation.annotationType())) {
                    // More robust to do a dynamic cast at runtime instead
                    // of compile-time only.
                    return annotationClass.cast(annotation);
                }
            }
            return null;
        }
        /**
         * 返回直接存在该元素岸上某类型的注释
         */
        default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
            return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass);
        }
        /**
         * 返回直接存在与该元素上的所有注释
         */
        Annotation[] getDeclaredAnnotations();
    

    运行时注解

    ButterKnife例子:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface BindView {
        int value();
    }
    
    public class ButterKnifeProcess {
        /**
         * 绑定Activity
         */
        public static void bind(final Activity activity) {
            Class annotationParent = activity.getClass();
            Field[] fields = annotationParent.getDeclaredFields();
            Method[] methods = annotationParent.getDeclaredMethods();
            // OnClick
            // 找到类里面所有的方法
            for (final Method method : methods) {
                //找到添加了OnClick注解的方法
                OnClick clickMethod = method.getAnnotation(OnClick.class);
                if (clickMethod != null && clickMethod.value().length != 0) {
                    for (int id : clickMethod.value()) {
                        final View view = activity.findViewById(id);
                        view.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                try {
                                    method.invoke(activity, view);
                                } catch (IllegalAccessException e) {
                                    e.printStackTrace();
                                } catch (InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }
            }
        }
    }
    
    public class MainActivity extends AppCompatActivity {
        //自动绑定view
        @BindView(R.id.text_abstract_processor)
        TextView mTextView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ButterKnifeProcess.bind(this);
        }
    }
    

    编译时注解

    注解处理器类

    /**
         * 每个Annotation Processor必须有一个空的构造函数。
         * 编译期间,init()会自动被注解处理工具调用,并传入ProcessingEnvironment参数,
         * 通过该参数可以获取到很多有用的工具类(Element,Filer,Messager等)
         */
        @Override
        public synchronized void init(ProcessingEnvironment processingEnvironment) {
            super.init(processingEnvironment);
        }
    
        /**
         * 用于指定自定义注解处理器(Annotation Processor)是注册给哪些注解的(Annotation),
         * 注解(Annotation)指定必须是完整的包名+类名
         */
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            return super.getSupportedAnnotationTypes();
        }
    
        /**
         * 用于指定你的java版本,一般返回:SourceVersion.latestSupported()
         */
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return SourceVersion.latestSupported();
        }
    
        /**
         * Annotation Processor扫描出的结果会存储进roundEnvironment中,可以在这里获取到注解内容,编写你的操作逻辑。
         * 注意:process()函数中不能直接进行异常抛出,否则程序会异常崩溃
         */
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            return false;
        }
    
    Element子类 解释
    TypeElement 类或接口元素
    VariableElement 字段、enum常量、方法或构造方法参数、局部变量或异常参数元素
    ExecutableElement 类或接口的方法、构造方法,或者注解类型元素
    PackageElement 包元素
    TypeParameterElement 类、接口、方法或构造方法元素的泛型参数
    /**
         * 返回此元素定义的类型,int,long这些
         */
        TypeMirror asType();
    
        /**
         * 返回此元素的种类:包、类、接口、方法、字段
         */
        ElementKind getKind();
    
        /**
         * 返回此元素的修饰符:public、private、protected
         */
        Set<Modifier> getModifiers();
    
        /**
         * 返回此元素的简单名称(类名)
         */
        Name getSimpleName();
    
        /**
         * 返回封装此元素的最里层元素。
         * 如果此元素的声明在词法上直接封装在另一个元素的声明中,则返回那个封装元素;
         * 如果此元素是顶层类型,则返回它的包;
         * 如果此元素是一个包,则返回 null;
         * 如果此元素是一个泛型参数,则返回 null.
         */
        Element getEnclosingElement();
    
        /**
         * 返回此元素直接封装的子元素
         */
        List<? extends Element> getEnclosedElements();
    
        /**
         * 返回直接存在于此元素上的注解
         * 要获得继承的注解,可使用 getAllAnnotationMirrors
         */
        List<? extends AnnotationMirror> getAnnotationMirrors();
    
        /**
         * 返回此元素上存在的指定类型的注解
         */
        <A extends Annotation> A getAnnotation(Class<A> var1);
    
    注解解析器帮助类 解释
    Elements 一个用来处理Element的工具类
    Types 一个用来处理TypeMirror的工具类
    Filer 用于创建文件(比如创建class文件)
    Messager 用于输出,类似printf函数

    实例

    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.METHOD)
    public @interface JsBridgeMethod {
        String value() default "";
    }
    
    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.TYPE)
    public @interface JsBridgeApi {
        String value() default "";
    }
    
    @AutoService(Processor.class)
    public class JsBridgeAnnoProcessor extends AbstractProcessor {
        private Elements mElementUtils; //基于元素进行操作的工具方法
        private Filer mFileCreator;     //代码创建者
        private Messager mMessager;     //日志,提示者,提示错误、警告
        private Map<String, HashMap<String, String>> exposedMethodsByName = new HashMap<>();//做缓存用
        private Map<String, String> classNameByJsApiName = new HashMap<>();//类名存储
        private String packageName;
    
        @Override
        public synchronized void init(final ProcessingEnvironment processingEnv) {
            super.init(processingEnv);
            mElementUtils = processingEnv.getElementUtils();
            mFileCreator = processingEnv.getFiler();
            mMessager = processingEnv.getMessager();
        }
    
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return SourceVersion.latestSupported();
        }
    
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            Set<String> types = new LinkedHashSet<>();
            types.add(JsBridgeMethod.class.getCanonicalName());
            return types;
        }
    
     @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            final Set<? extends Element> elementsAnnotatedWith =
                    roundEnvironment.getElementsAnnotatedWith(JsBridgeMethod.class);
            for (Element element : elementsAnnotatedWith) {
                ExecutableElement executableElement = (ExecutableElement) element;
                final TypeElement typeElement = (TypeElement) executableElement.getEnclosingElement();
                final String s = mElementUtils.getPackageOf(typeElement).getQualifiedName().toString();
    
                mMessager.printMessage(Diagnostic.Kind.NOTE, "package===>" + s);
                if (!s.equals(packageName)) {
                    packageName = s;
                }
    
                final JsBridgeApi jsBridgeApi = typeElement.getAnnotation(JsBridgeApi.class);
                if (jsBridgeApi != null) {
                    String jsBridgeApiName = jsBridgeApi.value();
                    if ("".equals(jsBridgeApiName)) {
                        jsBridgeApiName = typeElement.getSimpleName().toString();
                    }
                    //完整类名
                    final String qualifiedName = typeElement.getQualifiedName().toString();
    
                    JsBridgeMethod jsBridgeMethod =
                            executableElement.getAnnotation(JsBridgeMethod.class);
                    //注解上的js方法名
                    String jsMethodName = jsBridgeMethod.value();
    
                    //真实方法名
                    final String methodName = executableElement.getSimpleName().toString();
    
                    if ("".equals(jsMethodName)) {
                        jsMethodName = methodName;
                    }
    
                    classNameByJsApiName.put(jsBridgeApiName, qualifiedName);
    
                    //查询缓存中有无存过这个类
                    HashMap<String, String> methodsByApi;
                    if (!exposedMethodsByName.containsKey(jsBridgeApiName)) {
                        methodsByApi = new HashMap<>();
                        exposedMethodsByName.put(jsBridgeApiName, methodsByApi);
                    } else {
                        methodsByApi = exposedMethodsByName.get(jsBridgeApiName);
                    }
                    methodsByApi.put(jsMethodName, methodName);
                }
            }
    
            writeJava();
            return true;
        }
    
    private void writeJava() {
            final ParameterizedTypeName hashMapType =
                    ParameterizedTypeName.get(ClassName.get(HashMap.class), ClassName.get(String.class),
                            ClassName.get(Method.class));
    
            final MethodSpec.Builder methodBuild = MethodSpec.methodBuilder("register")
                    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                    .returns(void.class)
                    .addParameter(ParameterizedTypeName.get(ClassName.get(Map.class),
                            ClassName.get(String.class), hashMapType), "exposedMethods");
    
            final CodeBlock.Builder codeBuilder = CodeBlock.builder();
            for (String jsApiName : exposedMethodsByName.keySet()) {
    
                String className = classNameByJsApiName.get(jsApiName);
                //分割 dot 需要转义
                final String[] split = className.split("\\.");
                String simpleName = split[split.length - 1];
    
                String methodMapName = "mMethodsMap" + simpleName;
                codeBuilder.add("HashMap<String, Method> $L = new HashMap<>();\n", methodMapName);
                final HashMap<String, String> methodNameByJsName = exposedMethodsByName.get(jsApiName);
                for (String jsName : methodNameByJsName.keySet()) {
                    codeBuilder.add(methodMapName
                                    + ".put($S,$L.class.getMethod($S,com.sample.jsbridgelibrary.webView.WebViewFragmentWrapper.class,String.class,com.sample.jsbridgelibrary.bridge.Callback.class));\n",
                            jsName, className, methodNameByJsName.get(jsName));
                }
    
                codeBuilder.add("exposedMethods.put($S,$L);\n", jsApiName, methodMapName);
            }
    
            final MethodSpec registerMethod = methodBuild.beginControlFlow("try")
                    .addStatement(codeBuilder.build())
                    .nextControlFlow("catch ($T e)", Exception.class)
                    .addStatement("e.printStackTrace()")
                    .endControlFlow()
                    .build();
    
            TypeSpec JsBridgeRegister = TypeSpec.classBuilder("JsBridgeRegister")
                    .addModifiers(Modifier.PUBLIC)
                    .addMethod(registerMethod)
                    .build();
    
            mMessager.printMessage(Diagnostic.Kind.NOTE, "javaFile package===>" + packageName);
            JavaFile javaFile = JavaFile.builder(packageName, JsBridgeRegister).build();
            //        mMessager.printMessage(Diagnostic.Kind.NOTE, javaFile.toString());
            try {
                javaFile.writeTo(mFileCreator);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    参考https://blog.csdn.net/wuyuxing24/article/details/81139846

    相关文章

      网友评论

          本文标题:Android注解笔记

          本文链接:https://www.haomeiwen.com/subject/lqbndctx.html