type
status
date
slug
summary
tags
category
icon
password
内容提要:
- Java 注解
- Router 原理
- URI 的组成
- 使用 apt ,url 映射一个 class 类文件
注解什么是注解?什么用处?常用注解Java 注解Android 注解库Null 性注解线程注解元注解注解处理器(Annotation Processing)原理用法调试Router 原理URI 基本概念基于注解为 url 生成匹配对象使用 RouterManager 打开匹配对象Android 常见使用注解的框架扩展参考文档
注解
什么是注解?
注解又称为标注,用于为代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。可以作用在类、方法、变量、参数和包等上。 你可以通俗的理解成“标签”,这个标签可以标记类、方法、变量、参数和包。
什么用处?
- 生成文档
- 标识代码,便于查看
- 格式检查(编译时)
- 注解处理(编译期生成代码、xml文件等;运行期反射解析;常用于三方框架)
常用注解
Java 注解
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。
Java内置了三种标准注解,其定义在java.lang中。
- @Override,表示当前的方法定义将覆盖超类中的方法。
- @Deprecated,被此注解标记的元素表示被废弃,如果程序员使用了注解为它的元素,那么编译器会发出警告。
- @SuppressWarnings,关闭不当的编译器警告信息。
这几种注解我们平时开发中肯定经常用到,但是你可能很少看到注解原来的样子。如下为注解的类,可以看到,除了@符号的使用以外,它基本与Java固有语法一致。只是注解上又增加了其他注解。
Android 注解库
support.annotation
是 Android 提供的注解库,与 Android Studio 内置的代码检查工具配合,注解可以帮助检测可能发生的问题,例如 null 指针异常和资源类型冲突等。使用前配置 在 Module 的
build.gradle
中添加配置 ”implementation 'com.android.support:support-annotations:版本号'“Null 性注解
@Nullable
可以为 null
@NonNull
不可为 null
线程注解
线程注解可以检查某个方法是否从特定类型的线程调用。支持以下线程注解:
- @MainThread
- @UiThread
- @WorkerThread
- @BinderThread
- @AnyThread
更多 android 注解请参考(利用注解改进代码检查)
元注解
元注解是由 java 提供的基础注解,负责注解其它注解。
元注解 | 说明 | 取值 |
@Target | 表示该注解可以用在什么地方 | ElementType.ANNOTATION_TYPE 可以应用于注释类型。
ElementType.CONSTRUCTOR 可以应用于构造函数。
ElementType.FIELD 可以应用于字段或属性。
ElementType.LOCAL_VARIABLE 可以应用于局部变量。
ElementType.METHOD 可以应用于方法级注释。
ElementType.PACKAGE 可以应用于包声明。
ElementType.PARAMETER 可以应用于方法的参数。
ElementType.TYPE 可以应用于类的任何元素。
|
@Retention | 表示需要在什么级别保存该注解信息 | SOURCE: 只在源码中有效 (编译时抛弃)
CLASS: 在 class 文件中有效(即 class 保留)
RUNTIME: 在运行时有效(即运行时保留) |
@Documented | 表示将此注解包含在Javadoc中 | ㅤ |
@Inherited | 表示允许子类继承父类中的注解 | ㅤ |
注解处理器(Annotation Processing)
原理
Annotation Processing 原理:编译过程中读源码,然后⽣成新的代码⽂件,再放在⼀起进⾏编译
用法
Annotation Processing ⽤法:
- resources/META-INF/services/javax.annotation.processing.Processor(或者使用 AutoService)
- 继承 AbstractProcessor
- 重写 getSupportedAnnotationTypes() 和 process()
- 依赖 annotationProcessor先测试⽣成 java ⽂件的功能:手写或使用 javapoet
- 自动生成代码
- 添加依赖
调试
Router 原理
路由的一些基础概念可先了解 WMRouter:美团外卖Android开源路由框架、阿里巴巴 ARouter
URI 基本概念
URI(Uniform Resource Identifier,统一资源标识符)是一个用于标识某一互联网资源名称的字符串。URI的组成如下图所示:
基于注解为 url 生成匹配对象
注解生成代码使用 apt ,如果需要 oop 模式代码可以借助 Poet 库,现在 kotlin 语言也支持注解生成代码(性能很差)。
Router 做的事情只有一个,就是将一条 Url 匹配到一个 Class。
比如 @Router("dafay://video/{video_id}/collection/{collection_id}") 我们使用 Routers.getDefault().resolve("dafay://video/1111111111/collection/0000000000") 进行解析,具体流程如下:
流程说明:
- Routers.getDefault() 类加载时在静态代码块里面进行初始化,把注解生成代码 Mapper 对象添加到一个 sMapperList 链表里面,并基于 priority 进行排序
- resolve 方法里面遍历 sMapperList 里面的 mapper 挨个进行 Matcher.match() 匹配,匹配分为两个部分,a. 匹配 Uri.parse(url) 转换后的 uri 的 Host 与 Scheme,b.匹配 path,匹配 path 并把对应的 key/value 添加到 bundle 中。 匹配结束包装成 MatchResult 对象。这个过程还可以为 Matcher 定义自己的匹配规则。
- filter 对 MatchResult 进行过滤,这个过程也可以添加在家的过滤规则。
使用 RouterManager 打开匹配对象
针对 Router 解析结果做一些额外工作,
例如通过 RouterManager.open(context,"dafay://video/1111111111/collection/0000000000")
流程说明:
- 生成 MatchResult 对象
- RouterDispatcher 处理
- RouterConsumer 消费,可以在这里不再打开页面而是做一下其它操作,在这之后 包装成 ZHIntent,
- 对 ZHIntent 进行转换
- 通过 startFragmentForResult 具体实现类去打开 ZhIntent,打开前对目标 Fragment 类注解进行获取,所有这个地方获取到的值应该会覆盖掉 Url 的参数值
Android 常见使用注解的框架
- JakeWharton/butterknife:Android 开发的 View 注入框架,轻松的省去findViewById 来找到 View 对象的步骤
- JUnit :Java语言的单元测试框架,可以大大缩短你的测试时间和准确度
- Dagger2:依赖注入框架
- Retrofit: RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装。Retrofit通过注解的方式,进行网络请求描述。
- Arouter:阿里 Arouter
扩展
- kapt 性能、ViewBinding vs DataBinding 性能
- 编译优化(增量编译等)