Fork me on GitHub

从零开始写一个 ARouter - base 基础功能 与 core 核心功能

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

      • src.main.java
        • com.alibaba.android.arouter
          • facade 提供注解和枚举的包
            • annotation 存放各种注解类的包
              • Autowired.java 自动注入的注解
              • Interceptor.java 拦截器的注解
              • Param.java(废弃) 参数注解: 被 Autowired 淘汰
              • Route.java 路由信息注解
            • enums 包含各种枚举类型的包
              • RouteType.java 路由类型的枚举
              • TypeKind.java 类型种类的枚举
            • model 包含模型类的包
              • RouteMeta.java 路由元信息的模型类
              • TypeWrapper.java 存储目标对象的泛型类型信息的类
    • arouter-api ARouter框架的API模块

      • src.main.java
        • com.alibaba.android.arouter
          • base 基础功能相关的包

          • core 核心功能相关的包

          • 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 类型工具类

arouter-api ARouter框架的API模块

base 基础功能相关的包

UniqueKeyTreeMap
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.base

import java.util.*

/**
* TreeMap with unique key.
*
* @author zhilong [Contact me.](mailto:zhilong.lzl@alibaba-inc.com)
* @version 1.0
* @since 2017/2/22 下午5:01
*/
class UniqueKeyTreeMap<K, V>(private val tipText: String) :
TreeMap<K, V>() {
override fun put(key: K, value: V): V? {
return if (containsKey(key)) {
throw RuntimeException(String.format(tipText, key))
} else {
super.put(key, value)
}
}
}

core 核心功能相关的包

AutowiredLifecyleCallback(废弃)
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
package com.alibaba.android.arouter.core

import android.annotation.TargetApi
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Build
import android.os.Bundle
import com.alibaba.android.arouter.launcher.ARouter

/**
* LifecycleCallback for autowired.
*
* @author zhilong [Contact me.](mailto:zhilong.lzl@alibaba-inc.com)
* @version 1.0
* @since 2017/2/21 上午11:28
*/
@Deprecated("")
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
class AutowiredLifecycleCallback : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
ARouter.getInstance().inject(activity)
}

override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
}

已经废弃,不废话

AutowiredServiceImpl
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
package com.alibaba.android.arouter.core

import android.content.Context
import android.util.LruCache
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.facade.service.AutowiredService
import com.alibaba.android.arouter.facade.template.ISyringe
import com.alibaba.android.arouter.utils.Consts.SUFFIX_AUTOWIRED

/**
* 自动注入服务的实现。
*
* 作者: zhilong [联系我](mailto:zhilong.lzl@alibaba-inc.com)
* 版本: 1.0
* 创建日期: 2017年2月28日 下午6:08
*/
@Route(path = "/arouter/service/autowired")
class AutowiredServiceImpl : AutowiredService {
private var classCache: LruCache<String, ISyringe>? = null
private var blackList: MutableList<String>? = null

/**
* 初始化方法。
*
* @param context 上下文
*/
fun init(context: Context?) {
classCache = LruCache<String, ISyringe>(50)
blackList = ArrayList()
}

/**
* 自动注入方法。
*
* @param instance 要进行注入的实例
*/
fun autowire(instance: Any) {
doInject(instance, null)
}

/**
* 递归注入方法。
*
* @param instance 调用该方法的实例
* @param parent 父类的Class
*/
private fun doInject(instance: Any, parent: Class<*>?) {
// 如果提供了父类的 Class 对象,则使用父类的 Class;否则,使用实例的 Class
val clazz = parent ?: instance.javaClass
// 获取适用于当前类的注入器实例
val syringe: ISyringe? = getSyringe(clazz)
// 如果存在适用的注入器实例
if (null != syringe) {
// 使用注入器进行注入
syringe.inject(instance)
}
// 获取当前类的父类的 Class 对象
val superClazz = clazz.superclass
// 如果存在父类,并且父类不是 Android 框架类
if (null != superClazz && !superClazz.name.startsWith("android")) {
// 递归调用 doInject 方法,继续为父类进行自动注入
doInject(instance, superClazz)
}
}

/**
* 获取注入器实例。
*
* @param clazz 类的Class
* @return 注入器实例
*/
private fun getSyringe(clazz: Class<*>): ISyringe? {
// 获取类的完整名称
val className = clazz.name
try {
// 检查类名是否在黑名单中,如果不在,则尝试获取对应的注入器
if (!blackList!!.contains(className)) {
// 从缓存中尝试获取注入器实例
var syringeHelper: ISyringe? = classCache!![className]
// 如果缓存中没有该注入器实例
if (null == syringeHelper) {
// 动态加载并创建注入器实例
syringeHelper = Class.forName(
clazz.name + SUFFIX_AUTOWIRED
).getConstructor()
.newInstance() as ISyringe
// 将创建的注入器实例缓存起来,以便下次使用
classCache!!.put(className, syringeHelper)
}
// 返回获取到的注入器实例
return syringeHelper
}
} catch (e: Exception) {
// 如果在获取注入器的过程中发生异常,将类名添加到黑名单中,表示该实例无需自动注入
blackList!!.add(className)
}
// 如果无法获取注入器实例,返回 null
return null
}
}

doInject 方法用于自动注入依赖到给定的实例(instance)中。

InstrumentationHook(废弃)
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
package com.alibaba.android.arouter.core

import android.app.Activity
import android.app.Instrumentation
import android.content.Intent
import com.alibaba.android.arouter.launcher.ARouter
import com.alibaba.android.arouter.utils.Consts
import com.alibaba.android.arouter.utils.TextUtils

/**
* 使用 ARouter.getInstance().inject(this) 来进行注入!
*
* Hook Instrumentation,为 Activity 的字段注入值。
* 仅支持普通 Activity,不包括单元测试。
*
* 作者:Alex [联系我](mailto:zhilong.liu@aliyun.com)
* 版本:1.0
* 创建日期:2016年11月24日 16:42
*/
@Deprecated("")
class InstrumentationHook : Instrumentation() {
/**
* Hook Instrumentation 的 newActivity 方法,进行注入。
*
* 执行进程的 [Activity] 对象的实例化。默认实现提供正常的系统行为。
*
* @param cl 用于实例化对象的类加载器。
* @param className 实现 Activity 对象的类的名称。
* @param intent 指定要实例化的活动类的 Intent 对象。
* @return 新创建的 Activity 对象。
*/
@Throws(
InstantiationException::class,
IllegalAccessException::class,
ClassNotFoundException::class
)
override fun newActivity(
cl: ClassLoader, className: String,
intent: Intent
): Activity {

// return (Activity)cl.loadClass(className).newInstance();
// 使用类加载器加载目标 Activity 类的定义
val targetActivity = cl.loadClass(className)
// 创建目标 Activity 的实例
val instanceOfTarget = targetActivity.newInstance()
// 检查是否可以自动注入
if (ARouter.canAutoInject()) {
// 从 Intent 中获取自动注入的参数
val autoInjectParams = intent.getStringArrayExtra(ARouter.AUTO_INJECT)
if (null != autoInjectParams && autoInjectParams.isNotEmpty()) {
// 遍历参数列表
for (paramsName in autoInjectParams) {
// 从 Intent 的 extras 中获取参数值
val value = intent.extras!![TextUtils.getLeft(paramsName)]
if (null != value) {
try {
// 获取目标 Activity 中的字段
val injectField =
targetActivity.getDeclaredField(TextUtils.getLeft(paramsName))
// 设置字段可访问
injectField.isAccessible = true
// 将提取的值注入到目标 Activity 的字段中
injectField[instanceOfTarget] = value
} catch (e: Exception) {
// 记录错误日志,包括异常信息
ARouter.logger.error(
Consts.TAG,
"为 Activity 注入值时发生错误![" + e.message + "]"
)
}
}
}
}
}
// 返回已注入值的目标 Activity 实例
return instanceOfTarget as Activity
}
}

已废弃,不废话

InterceptorServiceImpl
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
package com.alibaba.android.arouter.core

import android.content.Context
import com.alibaba.android.arouter.exception.HandlerException
import com.alibaba.android.arouter.facade.Postcard
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.facade.callback.InterceptorCallback
import com.alibaba.android.arouter.facade.service.InterceptorService
import com.alibaba.android.arouter.facade.template.IInterceptor
import com.alibaba.android.arouter.launcher.ARouter.logger
import com.alibaba.android.arouter.thread.CancelableCountDownLatch
import com.alibaba.android.arouter.utils.Consts.TAG
import com.alibaba.android.arouter.utils.MapUtils
import java.util.concurrent.TimeUnit

/**
* 所有拦截器的实现类
*
* @author zhilong [联系我](mailto:zhilong.lzl@alibaba-inc.com)
* @version 1.0
* @since 2017/2/23 下午2:09
*/
@Route(path = "/arouter/service/interceptor")
class InterceptorServiceImpl : InterceptorService {
/**
* 执行拦截操作
*
* @param postcard 路由信息,包含了路由的相关信息和配置。
* @param callback 拦截回调,用于在拦截器流程中通知下一步操作。
*/
fun doInterceptions(postcard: Postcard, callback: InterceptorCallback) {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
// 检查拦截器是否已经初始化
checkInterceptorsInitStatus()

// 如果拦截器未初始化完成,中断导航并抛出异常
if (!interceptorHasInit) {
callback.onInterrupt(HandlerException("拦截器初始化花费太长时间。"))
return
}

// 在后台线程中执行拦截器操作
LogisticsCenter.executor.execute(Runnable {
val interceptorCounter = CancelableCountDownLatch(Warehouse.interceptors.size())
try {
// 依次执行拦截器
_execute(0, interceptorCounter, postcard)

// 等待拦截器执行完成,超时时间由路由配置决定
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS)

// 如果有未执行的拦截器,取消导航
if (interceptorCounter.getCount() > 0) { // 如果没有返回任何内容,取消导航。
callback.onInterrupt(HandlerException("拦截器处理超时。"))
} else if (null != postcard.getTag()) { // 如果标签中有异常信息。
callback.onInterrupt(postcard.getTag() as Throwable)
} else {
// 所有拦截器执行完毕,继续路由导航
callback.onContinue(postcard)
}
} catch (e: Exception) {
// 拦截器执行过程中出现异常,中断导航并传递异常信息
callback.onInterrupt(e)
}
})
} else {
// 没有注册拦截器,直接继续路由导航
callback.onContinue(postcard)
}
}

/**
* 初始化拦截器
*
* @param context 上下文对象,用于在拦截器初始化时可能需要的上下文信息。
*/
fun init(context: Context?) {
LogisticsCenter.executor.execute(Runnable {
// 检查是否有已注册的拦截器
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
for ((_, interceptorClass): Map.Entry<Int?, Class<out IInterceptor?>> in Warehouse.interceptorsIndex.entrySet()) {
try {
// 实例化拦截器
val iInterceptor: IInterceptor =
interceptorClass.getConstructor().newInstance()

// 调用拦截器的初始化方法,传入上下文信息
iInterceptor.init(context)

// 将拦截器添加到仓库中,以供后续使用
Warehouse.interceptors.add(iInterceptor)
} catch (ex: Exception) {
// 如果初始化过程中发生异常,抛出自定义的异常
throw HandlerException(TAG.toString() + "ARouter初始化拦截器错误!名称 = [" + interceptorClass.name + "],原因 = [" + ex.message + "]")
}
}

// 标记拦截器已经初始化完成
interceptorHasInit = true

// 记录日志,表示拦截器初始化已完成
logger.info(TAG, "ARouter拦截器初始化完成。")

// 通知等待的线程,拦截器已经初始化完成
synchronized(interceptorInitLock) { interceptorInitLock.notifyAll() }
}
})
}

companion object {
private var interceptorHasInit = false
private val interceptorInitLock = Any()

/**
* 执行拦截器
*
* @param index 当前拦截器索引
* @param counter 拦截器计数器
* @param postcard 路由信息
*/
private fun _execute(index: Int, counter: CancelableCountDownLatch, postcard: Postcard) {
if (index < Warehouse.interceptors.size()) {
val iInterceptor: IInterceptor = Warehouse.interceptors.get(index)
iInterceptor.process(postcard, object : InterceptorCallback() {
fun onContinue(postcard: Postcard) {
// 最后一个拦截器执行完成,没有异常。
counter.countDown()
_execute(
index + 1,
counter,
postcard
) // 当计数器减少时,继续执行,但是索引大于拦截器的大小,此时不会继续执行。
}

fun onInterrupt(exception: Throwable?) {
// 最后一个拦截器执行出现严重异常。
postcard.setTag(
exception ?: HandlerException("没有消息。")
) // 保存异常消息以备份。
counter.cancel()
// 注意,可能回调中的线程已经更改,
// 然后捕获块(L207)将无效。
// 最糟糕的情况是线程更改为主线程,然后如果抛出此异常,则应用程序将崩溃!
// if (!Looper.getMainLooper().equals(Looper.myLooper())) { // 如果线程是主线程,则不应抛出异常。
// throw new HandlerException(exception.getMessage());
// }
}
})
}
}

private fun checkInterceptorsInitStatus() {
synchronized(interceptorInitLock) {
while (!interceptorHasInit) {
try {
interceptorInitLock.wait((10 * 1000).toLong())
} catch (e: InterruptedException) {
throw HandlerException(TAG.toString() + "拦截器初始化花费太长时间错误!原因 = [" + e.message + "]")
}
}
}
}
}
}

这个类是ARouter(Android路由框架)的核心拦截器服务实现类,它具有以下作用:

  1. 拦截器管理: 该类负责管理ARouter框架中的拦截器。拦截器是在路由导航过程中执行的一系列操作,用于处理路由请求或者对路由进行拦截和修改。
  2. 拦截器执行: 通过doInterceptions方法,该类执行了一系列的拦截器操作。在路由导航之前,它会依次调用已注册的拦截器,检查是否需要拦截路由请求或对请求进行修改。如果有拦截器拦截了请求,将触发拦截器的onInterrupt方法,否则,将继续执行下一个拦截器,直到所有拦截器都完成或者发生了异常。
  3. 拦截器初始化: 通过init方法,该类还负责初始化所有的拦截器。在ARouter框架初始化的过程中,会注册各种拦截器,这些拦截器需要在合适的时机进行初始化,以便在路由导航时能够正确地执行。
  4. 线程控制: 该类使用CancelableCountDownLatch来管理拦截器的执行,确保在所有拦截器执行完成或者超时时能够继续路由导航操作。同时,它还使用锁来控制拦截器的初始化过程,以确保在初始化完成之前不会执行路由导航。
LogisticsCenter
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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
package com.alibaba.android.arouter.core

import android.content.Context
import android.net.Uri
import com.alibaba.android.arouter.exception.HandlerException
import com.alibaba.android.arouter.exception.NoRouteFoundException
import com.alibaba.android.arouter.facade.Postcard
import com.alibaba.android.arouter.facade.enums.TypeKind
import com.alibaba.android.arouter.facade.model.RouteMeta
import com.alibaba.android.arouter.facade.template.IInterceptorGroup
import com.alibaba.android.arouter.facade.template.IProvider
import com.alibaba.android.arouter.facade.template.IProviderGroup
import com.alibaba.android.arouter.facade.template.IRouteGroup
import com.alibaba.android.arouter.facade.template.IRouteRoot
import com.alibaba.android.arouter.launcher.ARouter
import com.alibaba.android.arouter.launcher.ARouter.logger
import com.alibaba.android.arouter.utils.ClassUtils
import com.alibaba.android.arouter.utils.Consts
import com.alibaba.android.arouter.utils.Consts.AROUTER_SP_CACHE_KEY
import com.alibaba.android.arouter.utils.Consts.AROUTER_SP_KEY_MAP
import com.alibaba.android.arouter.utils.Consts.DOT
import com.alibaba.android.arouter.utils.Consts.ROUTE_ROOT_PAKCAGE
import com.alibaba.android.arouter.utils.Consts.SDK_NAME
import com.alibaba.android.arouter.utils.Consts.SEPARATOR
import com.alibaba.android.arouter.utils.Consts.SUFFIX_INTERCEPTORS
import com.alibaba.android.arouter.utils.Consts.SUFFIX_PROVIDERS
import com.alibaba.android.arouter.utils.Consts.SUFFIX_ROOT
import com.alibaba.android.arouter.utils.Consts.TAG
import com.alibaba.android.arouter.utils.MapUtils
import com.alibaba.android.arouter.utils.PackageUtils
import com.alibaba.android.arouter.utils.TextUtils
import java.lang.Boolean
import java.lang.reflect.InvocationTargetException
import java.util.*
import java.util.concurrent.ThreadPoolExecutor
import kotlin.Exception
import kotlin.Int
import kotlin.String
import kotlin.Throwable
import kotlin.Throws
import kotlin.arrayOf

/**
* LogisticsCenter 包含了所有的路由映射信息。
*
* 1. 在首次使用时创建实例。
* 2. 处理多模块之间的映射关系(*)
* 3. 解决重复组定义的复杂逻辑
*
* @author Alex [联系我](mailto:zhilong.liu@aliyun.com)
* @version 1.0
* @since 16/8/23 15:02
*/
object LogisticsCenter {
private var mContext: Context? = null
var executor: ThreadPoolExecutor? = null
private var registerByPlugin = false

/**
* arouter-auto-register 插件将在这个方法中生成代码
* 调用这个方法来注册所有的路由、拦截器和提供者
*/
private fun loadRouterMap() {
registerByPlugin = false
// 自动生成的注册代码由 Gradle 插件 arouter-auto-register 生成
// 看起来像下面这样:
// registerRouteRoot(new ARouter..Root..modulejava());
// registerRouteRoot(new ARouter..Root..modulekotlin());
}

/**
* 根据类名注册
* 为了解决主 dex 文件过大的问题,牺牲了一些效率
*/
private fun register(className: String) {
if (!TextUtils.isEmpty(className)) {
try {
val clazz = Class.forName(className)
val obj = clazz.getConstructor().newInstance()
if (obj is IRouteRoot) {
registerRouteRoot(obj as IRouteRoot)
} else if (obj is IProviderGroup) {
registerProvider(obj as IProviderGroup)
} else if (obj is IInterceptorGroup) {
registerInterceptor(obj as IInterceptorGroup)
} else {
logger.info(
TAG, "注册失败,类名:" + className
+ " 应该实现其中一个接口 IRouteRoot/IProviderGroup/IInterceptorGroup。"
)
}
} catch (e: Exception) {
logger.error(TAG, "注册类错误:$className", e)
}
}
}

/**
* 用于 arouter-auto-register 插件注册路由的方法
* @param routeRoot IRouteRoot 实现类,位于包 com.alibaba.android.arouter.core.routers
*/
private fun registerRouteRoot(routeRoot: IRouteRoot?) {
markRegisteredByPlugin()
if (routeRoot != null) {
routeRoot.loadInto(Warehouse.groupsIndex)
}
}

/**
* 用于 arouter-auto-register 插件注册拦截器的方法
* @param interceptorGroup IInterceptorGroup 实现类,位于包 com.alibaba.android.arouter.core.routers
*/
private fun registerInterceptor(interceptorGroup: IInterceptorGroup?) {
markRegisteredByPlugin()
if (interceptorGroup != null) {
interceptorGroup.loadInto(Warehouse.interceptorsIndex)
}
}

/**
* 用于 arouter-auto-register 插件注册提供者的方法
* @param providerGroup IProviderGroup 实现类,位于包 com.alibaba.android.arouter.core.routers
*/
private fun registerProvider(providerGroup: IProviderGroup?) {
markRegisteredByPlugin()
if (providerGroup != null) {
providerGroup.loadInto(Warehouse.providersIndex)
}
}

/**
* 标记已由 arouter-auto-register 插件注册
*/
private fun markRegisteredByPlugin() {
if (!registerByPlugin) {
registerByPlugin = true
}
}

/**
* LogisticsCenter 初始化,加载所有路由信息到内存中,需要在首次使用时进行初始化。
*/
@Synchronized
@Throws(HandlerException::class)
fun init(context: Context, tpe: ThreadPoolExecutor?) {
mContext = context
executor = tpe
try {
var startInit = System.currentTimeMillis()
// 首先通过插件加载路由信息
loadRouterMap()
if (registerByPlugin) {
logger.info(TAG, "通过 arouter-auto-register 插件加载路由映射信息。")
} else {
val routerMap: Set<String>

// 在调试模式或安装新版本时,每次都会重建路由映射
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "在调试模式下或安装新版本,重新构建路由映射。")
// 这些类是由 arouter-compiler 自动生成的
routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE)
if (!routerMap.isEmpty()) {
context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE)
.edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply()
}
PackageUtils.updateVersion(context) // 保存新版本名,当路由映射更新完成时使用
} else {
logger.info(TAG, "从缓存中加载路由映射信息。")
routerMap = HashSet(
context.getSharedPreferences(
AROUTER_SP_CACHE_KEY,
Context.MODE_PRIVATE
).getStringSet(AROUTER_SP_KEY_MAP, HashSet())
)
}
logger.info(
TAG,
"找到路由映射信息,映射大小 = " + routerMap.size + ",耗时 " + (System.currentTimeMillis() - startInit) + " 毫秒。"
)
startInit = System.currentTimeMillis()
for (className in routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// 这是根元素之一,加载根元素
(Class.forName(className).getConstructor()
.newInstance() as IRouteRoot).loadInto(Warehouse.groupsIndex)
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// 加载拦截器映射信息
(Class.forName(className).getConstructor()
.newInstance() as IInterceptorGroup).loadInto(Warehouse.interceptorsIndex)
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// 加载提供者映射信息
(Class.forName(className).getConstructor()
.newInstance() as IProviderGroup).loadInto(Warehouse.providersIndex)
}
}
}
logger.info(
TAG,
"加载根元素完成,耗时 " + (System.currentTimeMillis() - startInit) + " 毫秒。"
)
if (Warehouse.groupsIndex.size() === 0) {
logger.error(TAG, "未找到映射文件,请检查您的配置!")
}
if (ARouter.debuggable()) {
logger.debug(
TAG,
java.lang.String.format(
Locale.getDefault(),
"LogisticsCenter 已经加载,GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]",
Warehouse.groupsIndex.size(),
Warehouse.interceptorsIndex.size(),
Warehouse.providersIndex.size()
)
)
}
} catch (e: Exception) {
throw HandlerException(TAG.toString() + "ARouter 初始化物流中心异常! [" + e.message + "]")
}
}

/**
* 根据服务名构建 Postcard
*
* @param serviceName 接口名
* @return Postcard
*/
fun buildProvider(serviceName: String?): Postcard? {
val meta: RouteMeta = Warehouse.providersIndex.get(serviceName)
return if (null == meta) {
null
} else {
Postcard(meta.getPath(), meta.getGroup())
}
}

/**
* 根据路由元信息完成 Postcard 对象
*
* @param postcard 不完整的 Postcard,应由此方法完成。
*/
@Synchronized
fun completion(postcard: Postcard?) {
if (null == postcard) {
throw NoRouteFoundException(TAG.toString() + "没有 Postcard!")
}
val routeMeta: RouteMeta = Warehouse.routes.get(postcard.getPath())
if (null == routeMeta) {
// 可能不存在或尚未加载
if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
throw NoRouteFoundException(TAG.toString() + "没有匹配路径 [" + postcard.getPath() + "],在组 [" + postcard.getGroup() + "] 中。")
} else {
// 加载路由信息并缓存到内存中,然后从路由元信息中删除
try {
if (ARouter.debuggable()) {
logger.debug(
TAG,
java.lang.String.format(
Locale.getDefault(),
"开始加载组 [%s],由 [%s] 触发。",
postcard.getGroup(),
postcard.getPath()
)
)
}
addRouteGroupDynamic(postcard.getGroup(), null)
if (ARouter.debuggable()) {
logger.debug(
TAG,
java.lang.String.format(
Locale.getDefault(),
"组 [%s] 已经加载,由 [%s] 触发。",
postcard.getGroup(),
postcard.getPath()
)
)
}
} catch (e: Exception) {
throw HandlerException(TAG.toString() + "加载组元信息时发生致命异常。 [" + e.message + "]")
}
completion(postcard) // 重新加载
}
} else {
postcard.setDestination(routeMeta.getDestination())
postcard.setType(routeMeta.getType())
postcard.setPriority(routeMeta.getPriority())
postcard.setExtra(routeMeta.getExtra())
val rawUri: Uri = postcard.getUri()
if (null != rawUri) { // 尝试将参数设置到 Bundle 中
val resultMap: Map<String, String> = TextUtils.splitQueryParameters(rawUri)
val paramsType: Map<String, Int?> = routeMeta.getParamsType()
if (MapUtils.isNotEmpty(paramsType)) {
// 根据参数类型设置值,仅对使用 @Param 注解的参数有效
for ((key, value): Map.Entry<String, Int?> in paramsType) {
setValue(
postcard,
value,
key,
resultMap[key]
)
}

// 保存需要自动注入的参数名
postcard.getExtras().putStringArray(
ARouter.AUTO_INJECT,
paramsType.keys.toArray(arrayOf<String>())
)
}

// 保存原始 URI
postcard.withString(ARouter.RAW_URI, rawUri.toString())
}
when (routeMeta.getType()) {
PROVIDER -> {
// 这是提供者,所以必须实现 IProvider 接口
val providerMeta: Class<out IProvider?> = routeMeta.getDestination()
var instance: IProvider? = Warehouse.providers.get(providerMeta)
if (null == instance) { // 没有此提供者的实例
val provider: IProvider
try {
provider = providerMeta.getConstructor().newInstance()
provider.init(mContext)
Warehouse.providers.put(providerMeta, provider)
instance = provider
} catch (e: Exception) {
logger.error(TAG, "初始化提供者失败!", e)
throw HandlerException("初始化提供者失败!")
}
}
postcard.setProvider(instance)
postcard.greenChannel() // 提供者应跳过所有拦截器
}
FRAGMENT -> postcard.greenChannel() // Fragment 不需要拦截器
else -> {}
}
}
}

/**
* 根据已知类型设置值
*
* @param postcard postcard
* @param typeDef 类型
* @param key 键
* @param value 值
*/
private fun setValue(postcard: Postcard, typeDef: Int?, key: String, value: String?) {
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
return
}
try {
if (null != typeDef) {
if (typeDef === TypeKind.BOOLEAN.ordinal()) {
postcard.withBoolean(key, Boolean.parseBoolean(value))
} else if (typeDef === TypeKind.BYTE.ordinal()) {
postcard.withByte(key, value!!.toByte())
} else if (typeDef === TypeKind.SHORT.ordinal()) {
postcard.withShort(key, value!!.toShort())
} else if (typeDef === TypeKind.INT.ordinal()) {
postcard.withInt(key, value!!.toInt())
} else if (typeDef === TypeKind.LONG.ordinal()) {
postcard.withLong(key, value!!.toLong())
} else if (typeDef === TypeKind.FLOAT.ordinal()) {
postcard.withFloat(key, value!!.toFloat())
} else if (typeDef === TypeKind.DOUBLE.ordinal()) {
postcard.withDouble(key, value!!.toDouble())
} else if (typeDef === TypeKind.STRING.ordinal()) {
postcard.withString(key, value)
} else if (typeDef === TypeKind.PARCELABLE.ordinal()) {
// TODO : 如何使用字符串描述可传递的值?
} else if (typeDef === TypeKind.OBJECT.ordinal()) {
postcard.withString(key, value)
} else { // 兼容编译器 SDK 1.0.3,在该版本中,字符串类型 = 18
postcard.withString(key, value)
}
} else {
postcard.withString(key, value)
}
} catch (ex: Throwable) {
logger.warning(Consts.TAG, "LogisticsCenter setValue 失败!" + ex.message)
}
}

/**
* 挂起业务,清除缓存。
*/
fun suspend() {
Warehouse.clear()
}

@Synchronized
@Throws(
NoSuchMethodException::class,
IllegalAccessException::class,
InvocationTargetException::class,
InstantiationException::class
)
fun addRouteGroupDynamic(groupName: String?, group: IRouteGroup?) {
if (Warehouse.groupsIndex.containsKey(groupName)) {
// 如果已包含此组,但尚未加载
// 先加载此组,因为动态路由具有较高的优先级。
Warehouse.groupsIndex.get(groupName).getConstructor().newInstance()
.loadInto(Warehouse.routes)
Warehouse.groupsIndex.remove(groupName)
}

// 覆盖旧组。
if (null != group) {
group.loadInto(Warehouse.routes)
}
}
}

这个类是ARouter库的核心组件之一,它的主要作用是负责管理和维护ARouter路由框架中的各种映射关系和配置信息,以便实现路由功能。以下是这个类的主要作用描述:

  1. 加载路由映射信息: LogisticsCenter负责加载和管理所有的路由映射信息。这些路由映射信息包括路由路径、路由分组、拦截器、提供者等相关信息,它们在ARouter框架中用于实现路由跳转和服务提供。

  2. 支持自动注册: 通过ARouter的插件机制,LogisticsCenter可以支持自动注册路由信息,使得开发者无需手动配置路由信息,提高了开发效率。插件会自动生成代码来调用LogisticsCenter的方法注册路由信息。

  3. 初始化和管理线程池: LogisticsCenter负责初始化和管理线程池,用于异步加载路由信息和执行路由任务。线程池的管理有助于提高ARouter框架的性能和并发处理能力。

  4. 动态加载路由信息: 当需要跳转到某个路由时,LogisticsCenter会根据路由信息动态加载相关的路由元信息,包括路由组信息和拦截器信息,以便进行路由跳转和拦截器处理。

  5. 提供路由跳转和服务提供支持: LogisticsCenter提供了一系列方法,用于构建路由跳转的Postcard对象和获取服务提供者的实例。它还负责处理路由跳转的逻辑,包括路由路径匹配、拦截器处理和服务提供。

  6. 支持路由信息的缓存和更新: LogisticsCenter支持路由信息的缓存和更新,以提高ARouter框架的性能。当路由信息有更新时,可以通过插件机制重新生成路由映射信息。

总之,LogisticsCenter是ARouter框架中的核心组件,它通过加载、管理和动态获取路由信息,实现了路由跳转和服务提供的功能,提供了便捷的路由框架和服务化解决方案。

Warehouse
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
package com.alibaba.android.arouter.core

import com.alibaba.android.arouter.base.UniqueKeyTreeMap
import com.alibaba.android.arouter.facade.model.RouteMeta
import com.alibaba.android.arouter.facade.template.IInterceptor
import com.alibaba.android.arouter.facade.template.IProvider
import com.alibaba.android.arouter.facade.template.IRouteGroup

/**
* 路由元信息和其他数据的存储仓库。
*
* Warehouse(仓库)负责存储路由元信息以及其他相关数据。
*
* @author zhilong [Contact me.](mailto:zhilong.lzl@alibaba-inc.com)
* @version 1.0
* @since 2017/2/23 下午1:39
*/
internal object Warehouse {
// 缓存路由组和路由元信息
var groupsIndex: MutableMap<String, Class<out IRouteGroup?>> =
HashMap<String, Class<out IRouteGroup?>>()
var routes: MutableMap<String, RouteMeta> = HashMap<String, RouteMeta>()

// 缓存服务提供者
var providers: MutableMap<Class<*>, IProvider> = HashMap<Class<*>, IProvider>()
var providersIndex: MutableMap<String, RouteMeta> = HashMap<String, RouteMeta>()

// 缓存拦截器
var interceptorsIndex: MutableMap<Int, Class<out IInterceptor?>> =
UniqueKeyTreeMap("多个拦截器使用相同的优先级 [%s]")
var interceptors: MutableList<IInterceptor> = ArrayList<IInterceptor>()

/**
* 清空仓库中的数据。
*/
fun clear() {
routes.clear()
groupsIndex.clear()
providers.clear()
providersIndex.clear()
interceptors.clear()
interceptorsIndex.clear()
}
}

这个类是ARouter框架内部的一个存储仓库,用于缓存路由元信息、路由组信息、服务提供者信息以及拦截器信息等相关数据。这些数据在ARouter框架中用于实现路由跳转和服务提供功能。

,