Fork me on GitHub

从零开始写一个 ARouter - router-annotation 路由注解模块

  • ARouter
    • router-annotation 路由注解模块

    • arouter-api ARouter框架的API模块

      • src.main.java
        • com.alibaba.android.arouter
          • base 基础功能相关的包
            • UniqueKeyTreeMap.java 唯一键树形映射的类
          • core 核心功能相关的包
            • AutowiredLifecyleCallback.java(废弃) 自动注入生命周期回调的类
            • AutowiredServiceImpl.java 自动注入服务的实现类
            • InstrumentationHook.java(废弃) 仪表钩子的类
            • InterceptorServiceImpl.java 拦截器服务的实现类
            • LogisticsCenter.java 物流中心的类
            • Warehouse.java 仓库的类
          • exception 异常相关的包
            • HandlerException.java 处理异常的类
            • InitException.java 初始化异常的类
            • NoRouteFoundException.java 未找到路由的异常类
          • facade 提供各种服务和回调的包
            • callback 回调相关的包
              • InterceptorCallback.java 拦截器回调的接口
              • NavigationCallback.java 导航回调的接口
              • NoRouteFoundException.java 未找到路由的异常接口
          • service 服务相关的包
            • AutowiredService.java 自动注入服务的接口
            • ClassLoaderService.java 类加载器服务的接口
            • DegradeService.java 降级服务的接口
            • InterceptorService.java 拦截器服务的接口
            • PathReplaceService.java 路径替换服务的接口
            • PretreatmentService.java 预处理服务的接口
            • SerializationService.java 序列化服务的接口
          • template 模板相关的包
            • IInterceptor.java 拦截器接口
            • IInterceptorGroup.java 拦截器分组接口
            • Ilogger.java 日志记录器接口
            • IPolicy.java 策略接口
            • IProvider.java 提供者接口
            • IProviderGroup.java 提供者分组接口
            • IRouteGroup.java 路由分组接口
            • IRouteRoot.java 路由根接口
            • Isyringe.java 注射器接口
            • Postcard.java 路由信息封装类
          • launcher 启动器: 包含一些用于启动ARouter框架的类和线程管理相关的类。
            • _Arouter.java ARouter框架的内部启动类,用于初始化ARouter。
            • Arouter.java ARouter框架的启动类,用于初始化ARouter。
          • thread (线程)包含了与线程管理相关的类。
            • CancelableCountDownLatch.java 可取消的倒计时计数器,用于线程同步。
            • DefaultPoolExecutor.java 默认的线程池执行器,用于执行异步任务。
            • DefaultThreadFactory.java 默认线程工厂,用于创建线程。
          • utils 工具类。
            • ClassUtils.java 用于操作类的实用工具类。
            • Consts.java 包含一些常量值的类。
            • DefaultLogger.java 默认的日志记录器类。
            • MapUtils.java 用于操作地图数据的实用工具类。
            • PackageUtils.java 用于操作包信息的实用工具类。
            • TextUtils.java 用于操作文本数据的实用工具类。
    • arouter-compiler

      • src.main.java
        • com.alibaba.android.arouter
          • compiler 编译相关的包
            • entity 实体类相关的包
              • RouteDoc.java 路由文档实体类
            • processor 处理器相关的包
              • AutowiredProcessor.java 自动注入处理器
              • BaseProcessor.java 基础处理器
              • InterceptorProcessor.java 拦截器处理器
              • RouteProcessor.java 路由处理器
            • utils 工具类相关的包
              • Consts.java 常量类
              • Logger.java 日志记录器类
              • TypeUtils.java 类型工具类

router-annotation 路由注解模块

annotation 存放各种注解类的包

Autowired

自动注入的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.alibaba.android.arouter.facade.annotation

/**
* Annotation for field, which need autowired.
* 用于需要自动注入的字段的注解。
*
* @author zhilong [Contact me.](mailto:zhilong.lzl@alibaba-inc.com)
* @version 1.0
* @since 2017/2/20 下午4:26
*/
@Target(AnnotationTarget.FIELD) // 表示该注解只能用于字段上
@kotlin.annotation.Retention(AnnotationRetention.BINARY) // 表示该注解的生命周期为编译期
annotation class Autowired( // Mark param's name or service name.
// 标记参数的名称或服务名称
val name: String = "", // If required, app will be crash when value is null.
// Primitive type wont be check!
// 如果设置为true,在数值为null时应用程序将崩溃。不会检查原始类型!
val required: Boolean = false, // Description of the field
// 字段的描述信息
val desc: String = ""
)

标记需要注入的字段:在你的类中,标记需要进行自动注入的字段。使用 @Autowired 注解,例如:

1
2
3
4
5
6
7
8
9
10
import com.alibaba.android.arouter.facade.annotation.Autowired;

// ...

public class MyClass {
@Autowired
private MyDependency myDependency;

// ...
}

在这个示例中,myDependency 字段被标记为需要自动注入的依赖对象。

假设你有两个相同类型的依赖对象 MyDependency,但它们在功能上略有不同,你需要指定要注入哪一个。

1
2
3
4
5
6
7
8
9
10
11
12
javaCopy code
import com.alibaba.android.arouter.facade.annotation.Autowired;

public class MyClass {
@Autowired(name = "dependencyA")
private MyDependency dependencyA;

@Autowired(name = "dependencyB")
private MyDependency dependencyB;

// ...
}
Interceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.alibaba.android.arouter.facade.annotation

/**
* 标记拦截器以拦截路由。
* 注意:此注解仅可用于标记#{IInterceptor}的实现!!!
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 16/8/23 14:03
*/
@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) // 表示该注解只能用于类上
@kotlin.annotation.Retention(AnnotationRetention.BINARY) // 表示该注解的生命周期为编译期
annotation class Interceptor(
/**
* 拦截器的优先级,ARouter将按优先级执行它们。
*/
val priority: Int,
/**
* 拦截器的名称,可能用于生成javadoc。
*/
val name: String = "Default"
)

要使用 @Interceptor 注解,你需要将其标记在实现了 IInterceptor 接口的类上,以定义一个拦截器。然后,你可以使用这个拦截器来拦截路由操作。下面是使用 @Interceptor 注解的一般步骤:

创建一个实现了 IInterceptor 接口的类,该类将用作拦截器。确保类实现了接口中的 process 方法,该方法定义了拦截器的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kotlinCopy code
import com.alibaba.android.arouter.facade.annotation.Interceptor
import com.alibaba.android.arouter.facade.template.IInterceptor
import com.alibaba.android.arouter.facade.callback.InterceptorCallback

@Interceptor(priority = 1, name = "ExampleInterceptor")
class ExampleInterceptor : IInterceptor {
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
// 在这里编写拦截器的逻辑
// 可以在进入路由之前或之后执行一些操作

// 最后,调用 callback.onContinue(postcard) 继续路由操作,或者 callback.onInterrupt(exception) 中断路由操作
callback?.onContinue(postcard)
}
}
Param(废弃)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.alibaba.android.arouter.facade.annotation

/**
* 用于标记页面参数的注解。
* 此注解已被弃用,请使用 'Autowired' 代替!
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 2016/11/22 18:01
*/
@Target(AnnotationTarget.FIELD) // 表示该注解只能用于字段上
@kotlin.annotation.Retention(AnnotationRetention.BINARY) // 表示该注解的生命周期为编译期
@Deprecated("") // 表示该注解已被弃用
annotation class Param(
/**
* 字段名称
*/
val name: String = "",
/**
* 字段的描述信息
*/
val desc: String = "No desc."
)

既已废弃,不浪费时间

Route
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.alibaba.android.arouter.facade.annotation

/**
* 标记页面可由路由器路由。
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 16/8/15 下午9:29
*/
@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) // 表示该注解只能用于类上
@kotlin.annotation.Retention(AnnotationRetention.BINARY) // 表示该注解的生命周期为编译期
annotation class Route(
/**
* 路由的路径
*/
val path: String,
/**
* 用于合并路由,组名必须使用常见单词!!!
*/
val group: String = "",
/**
* 路由的名称,用于生成javadoc。
*/
val name: String = "",
/**
* 额外的数据,可以由用户设置。
* 注意:您应该使用整数数值表示开关,通过位进行标记。例如:10001010101010
*/
val extras: Int = Int.MIN_VALUE,
/**
* 路由的优先级。
*/
val priority: Int = -1
)

这个类定义了一个用于标记页面可由路由器路由的注解 @Route。该注解包含了五个元素,分别表示路由的路径、组名、名称、额外数据和优先级。

创建一个页面类,并在该类上添加 @Route 注解,以标记这个页面可以被路由器路由。

1
2
3
4
5
6
7
import com.alibaba.android.arouter.facade.annotation.Route

// 使用 @Route 注解标记这个页面
@Route(path = "/example/activity")
class ExampleActivity : AppCompatActivity() {
// 页面的代码...
}

在上面的示例中,我们创建了一个名为 ExampleActivity 的页面类,并使用 @Route 注解标记了这个页面的路由路径为 "/example/activity"

enums 包含各种枚举类型的包

RouteType
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.alibaba.android.arouter.facade.enums

/**
* 路由类型的枚举。
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 16/8/23 22:33
*/
enum class RouteType(// 未知类型的路由
var id: Int, var className: String
) {
ACTIVITY(0, "android.app.Activity"), // Activity类型的路由
SERVICE(1, "android.app.Service"), // Service类型的路由
PROVIDER(2, "com.alibaba.android.arouter.facade.template.IProvider"), // Provider类型的路由
CONTENT_PROVIDER(-1, "android.app.ContentProvider"), // ContentProvider类型的路由
BOARDCAST(-1, ""), // Broadcast类型的路由
METHOD(-1, ""), // Method类型的路由
FRAGMENT(-1, "android.app.Fragment"), // Fragment类型的路由
UNKNOWN(-1, "Unknown route type");

fun setId(id: Int): RouteType {
this.id = id
return this
}

fun setClassName(className: String): RouteType {
this.className = className
return this
}

companion object {
fun parse(name: String): RouteType {
for (routeType in values()) {
if (routeType.className == name) {
return routeType
}
}
return UNKNOWN
}
}
}
TypeKind
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.alibaba.android.arouter.facade.enums

/**
* 字段类型的种类枚举。
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 2017-03-16 19:13:38
*/
enum class TypeKind {
// 基本类型
BOOLEAN, // 布尔类型
BYTE, // 字节类型
SHORT, // 短整型
INT, // 整型
LONG, // 长整型
CHAR, // 字符类型
FLOAT, // 单精度浮点型
DOUBLE, // 双精度浮点型

// 其他类型
STRING, // 字符串类型
SERIALIZABLE, // 可序列化类型
PARCELABLE, // Parcelable类型
OBJECT // 对象类型
}

model 包含模型类的包

RouteMeta
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package com.alibaba.android.arouter.facade.model

import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.miao.router.RouteType

/**
* 包含基本路由信息的类。
*
* @author Alex [联系我。](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 16/8/24 09:45
*/
class RouteMeta {
var type: RouteType? = null // 路由类型
private set

private var rawType: javax.lang.model.element.Element? = null // 路由的原始类型

var destination : Class<*>? = null // 目标类
private set

var path : String? = null // 路由路径
private set

var group: String? = null // 路由分组
private set

var priority = -1 // 优先级,数值越小优先级越高
private set

var extra = 0// 额外数据
private set

var paramsType: Map<String?, Int?>? = null // 参数类型
private set

var name: String? = null

var injectConfig: Map<String, Autowired>? = null // 缓存注入配置信息

constructor() {}

/**
* Type
*
* @param route 路由
* @param destination 目标类
* @param type 类型
*/
constructor(
route: Route,
destination: Class<*>?,
type: RouteType?
) : this(
type,
null,
destination,
route.name(),
route.path(),
route.group(),
null,
route.priority(),
route.extras()
) {
}

/**
* Type
*
* @param route 路由
* @param rawType 原始类型
* @param type 类型
* @param paramsType 参数类型
*/
constructor(
route: Route,
rawType: javax.lang.model.element.Element?,
type: RouteType?,
paramsType: Map<String?, Int?>?
) : this(
type,
rawType,
null,
route.name(),
route.path(),
route.group(),
paramsType,
route.priority(),
route.extras()
) {
}

/**
* Type
*
* @param type 类型
* @param rawType 原始类型
* @param destination 目标类
* @param path 路径
* @param group 分组
* @param paramsType 参数类型
* @param priority 优先级
* @param extra 额外数据
*/
constructor(
type: RouteType?,
rawType: javax.lang.model.element.Element?,
destination: Class<*>?,
name: String?,
path: String?,
group: String?,
paramsType: Map<String?, Int?>?,
priority: Int,
extra: Int
) {
this.type = type
this.name = name
this.destination = destination
this.rawType = rawType
this.path = path
this.group = group
this.paramsType = paramsType
this.priority = priority
this.extra = extra
}

fun setParamsType(paramsType: Map<String?, Int?>?): RouteMeta {
this.paramsType = paramsType
return this
}

fun getRawType(): javax.lang.model.element.Element? {
return rawType
}

fun setRawType(rawType: javax.lang.model.element.Element?): RouteMeta {
this.rawType = rawType
return this
}

fun setType(type: RouteType?): RouteMeta {
this.type = type
return this
}

fun setDestination(destination: Class<*>?): RouteMeta {
this.destination = destination
return this
}

fun setPath(path: String?): RouteMeta {
this.path = path
return this
}

fun setGroup(group: String?): RouteMeta {
this.group = group
return this
}

fun setPriority(priority: Int): RouteMeta {
this.priority = priority
return this
}

fun setExtra(extra: Int): RouteMeta {
this.extra = extra
return this
}

override fun toString(): String {
return "RouteMeta{" +
"type=" + type +
", rawType=" + rawType +
", destination=" + destination +
", path='" + path + '\'' +
", group='" + group + '\'' +
", priority=" + priority +
", extra=" + extra +
", paramsType=" + paramsType +
", name='" + name + '\'' +
'}'
}

companion object {
/**
* For versions of 'compiler' less than 1.0.7, contain 1.0.7
*
* @param type 类型
* @param destination 目标类
* @param path 路径
* @param group 分组
* @param priority 优先级
* @param extra 额外数据
* @return this
*/
fun build(
type: RouteType?,
destination: Class<*>?,
path: String?,
group: String?,
priority: Int,
extra: Int
): RouteMeta {
return RouteMeta(type, null, destination, null, path, group, null, priority, extra)
}

/**
* For versions of 'compiler' greater than 1.0.7
*
* @param type 类型
* @param destination 目标类
* @param path 路径
* @param group 分组
* @param paramsType 参数类型
* @param priority 优先级
* @param extra 额外数据
* @return this
*/
fun build(
type: RouteType?,
destination: Class<*>?,
path: String?,
group: String?,
paramsType: Map<String?, Int?>?,
priority: Int,
extra: Int
): RouteMeta {
return RouteMeta(
type,
null,
destination,
null,
path,
group,
paramsType,
priority,
extra
)
}
}
}

private RouteType type:表示路由的类型,可能是普通路由、自动注入、或者其他类型。
private Element rawType:表示路由的原始类型的元素。
private Class<?> destination:表示目标类,即路由到哪个页面。
private String path:表示路由的路径,用于唯一标识一个路由。
private String group:表示路由的分组,通常用于组织路由。
private int priority:表示路由的优先级,数值越小表示优先级越高。
private int extra:表示额外的数据,可以用于传递一些标记或开关。
private Map<String, Integer> paramsType:表示参数类型的映射。
private String name:表示路由的名称。

RouteMeta 是 Route 原子信息与其构建类

TypeWrapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.alibaba.android.arouter.facade.model

import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

/**
* 用于获取目标对象的类型。
*
* @param <T> 泛型类型
* @since 17/10/26 11:56:22
</T> */
class TypeWrapper<T> protected constructor() {
/**
* 获取目标对象的类型。
*
* @return 目标对象的类型
*/
val type: Type // 存储目标对象的类型信息

init {
val superClass = javaClass.genericSuperclass
type =
(superClass as ParameterizedType).actualTypeArguments[0] // 获取泛型类型参数
}
}

通过 Java 反射获取当前类的父类,然后从父类中获取泛型参数的类型信息,并将其赋值给 type 字段。这样,这个类就能够存储目标对象的泛型类型信息。

,