Android项目解耦--路由框架ARouter源码解析

前言

上一篇文章Android项目解耦–路由框架ARouter的使用讲述了ARouter在项目中的使用,这边文章主要对ARouter的源码进行学习和分析。

ARouter的结构

ARouter主要由三部分组成,包括对外提供的api调用模块、注解模块以及编译时通过注解生产相关的类模块。

  • arouter-annotation注解的声明和信息存储类的模块
  • arouter-compiler编译期解析注解信息并生成相应类以便进行注入的模块
  • arouter-api核心调用Api功能的模块

annotation模块

arouter-annotation.png

RouteInterceptorAutowired都是我们在开发是需要的注解。

compiler模块

arouter-compiler.png

AutoWiredProcessorInterceptorProcessorRouteProcessor分别为annotation模块对应的AutowiredInterceptorRoute在项目编译时产生相关的类文件。

build-source.png

api模块

主要是ARouter具体实现和对外暴露使用的api。api部分我们可以参数上一篇文章Android项目解耦–路由框架ARouter的使用,ARouter实现我们具体在下面讲解。

ARouter的工作流程

arouter-init.png

Arouter初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public final class ARouter {
/**
* Init, it must be call before used router.
*/
public static void init(Application application) {
if (!hasInit) {
logger = _ARouter.logger;
_ARouter.logger.info(Consts.TAG, "ARouter init start.");
hasInit = _ARouter.init(application);

if (hasInit) {
_ARouter.afterInit();
}

_ARouter.logger.info(Consts.TAG, "ARouter init over.");
}
}
}

_ARouter初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final class _ARouter {
protected static synchronized boolean init(Application application) {
mContext = application;
LogisticsCenter.init(mContext, executor);
logger.info(Consts.TAG, "ARouter init success!");
hasInit = true;

// It's not a good idea.
// if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// application.registerActivityLifecycleCallbacks(new AutowiredLifecycleCallback());
// }
return true;
}
}

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
public class LogisticsCenter {
/**
* LogisticsCenter init, load all metas in memory. Demand initialization
*/
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;
try {
long startInit = System.currentTimeMillis();
Set<String> routerMap;
//debug或者版本更新的时候每次都重新加载router信息
// It will rebuild router map every times when debuggable.
if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
// These class was generate by arouter-compiler.
//加载alibaba.android.arouter.routes包下载的类
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); // Save new version name when router map update finish.
} else {
logger.info(TAG, "Load router map from cache.");
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
}

logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
startInit = System.currentTimeMillis();

for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
//导入ARouter$$Root$$app.java,初始化Warehouse.groupsIndex集合
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
//导入ARouter$$Interceptors$$app.java,初始化Warehouse.interceptorsIndex集合
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// Load providerIndex
//导入ARouter$$Providers$$app.java,初始化Warehouse.providersIndex集合
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}

/*******部分代码省略********/
} catch (Exception e) {
throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
}
}
}

ARouter的结构

结构.png

ARouter、Postcard、LogisticsCenter、DegradeService、PathReplaceService、InterceptroService这五个部分基本构成了ARouter的主体架构。

ARouter(_ARouter)模块

ARouter主要提供对外调用的api,_ARouter路由协议的具体实现类。

获取服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final class _ARouter {
protected <T> T navigation(Class<? extends T> service) {
try {
Postcard postcard = LogisticsCenter.buildProvider(service.getName());

// Compatible 1.0.5 compiler sdk.
if (null == postcard) { // No service, or this service in old version.
postcard = LogisticsCenter.buildProvider(service.getSimpleName());
}

LogisticsCenter.completion(postcard);
return (T) postcard.getProvider();
} catch (NoRouteFoundException ex) {
logger.warning(Consts.TAG, ex.getMessage());
return null;
}
}
}

跳转协议

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
final class _ARouter {
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
/**************部分代码省略***************/
if (null != callback) {
callback.onLost(postcard);
} else { // No callback for this invoke, then we use the global degrade service.
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}
return null;
}

if (null != callback) {
callback.onFound(postcard);
}
//是否为绿色通道,是否进过拦截器处理
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
_navigation(context, postcard, requestCode, callback);
}
@Override
public void onInterrupt(Throwable exception) {
//中断处理
if (null != callback) {
callback.onInterrupt(postcard);
}
}
});
} else {
return _navigation(context, postcard, requestCode, callback);
}

return null;
}

private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
//没有上下文环境,就用Application的上下文环境
final Context currentContext = null == context ? mContext : context;
switch (postcard.getType()) {
case ACTIVITY:
// Build intent 构建跳转的intent
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());
// Set flags. 设置flag
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag.
//如果上下文不是Activity,则添加FLAG_ACTIVITY_NEW_TASK的flag
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
// Navigation in main looper. 切换到主线程中
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
if (requestCode > 0) { // Need start for result
ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
} else {
ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
}

if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version.
((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
}

if (null != callback) { // Navigation over.
callback.onArrival(postcard);
}
}
});

break;
case PROVIDER:
return postcard.getProvider();
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
Class fragmentMeta = postcard.getDestination();
try {
Object instance = fragmentMeta.getConstructor().newInstance();
if (instance instanceof Fragment) {
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
}

return instance;
} catch (Exception ex) {
logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
}
case METHOD:
case SERVICE:
default:
return null;
}

return null;
}
}

Postcard模块

postcard.png

Postcard主要为信息的携带者,内容是在构造一次路由信息的时候生产的,其继承于RouteMetaRouteMeta是在代码编译时生成的内容,主要在初始化WareHouse时对跳转信息做了缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Warehouse {
// Cache route and metas
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
static Map<String, RouteMeta> routes = new HashMap<>();

// Cache provider
static Map<Class, IProvider> providers = new HashMap<>();
static Map<String, RouteMeta> providersIndex = new HashMap<>();

// Cache interceptor
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
static List<IInterceptor> interceptors = new ArrayList<>();

static void clear() {
routes.clear();
groupsIndex.clear();
providers.clear();
providersIndex.clear();
interceptors.clear();
interceptorsIndex.clear();
}
}

我们先来看一下一些基础类的信息:

router-data.png
1
2
3
4
5
6
7
8
9
10
11
12
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$activity implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/Example1Activity", RouteMeta.build(RouteType.ACTIVITY, Example1Activity.class, "/example1activity", "activity", null, -1, 10));
atlas.put("/activity/FragActivity", RouteMeta.build(RouteType.ACTIVITY, FragActivity.class, "/activity/fragactivity", "activity", null, -1, -2147483648));
atlas.put("/activity/MainActivity", RouteMeta.build(RouteType.ACTIVITY, MainActivity.class, "/activity/mainactivity", "activity", null, -1, -2147483648));
atlas.put("/activity/ParamsCallActivity", RouteMeta.build(RouteType.ACTIVITY, ParamsCallActivity.class, "/activity/paramscallactivity", "activity", new java.util.HashMap<String, Integer>(){{put("obj", 10); put("name", 8); put("girl", 0); put("age", 3); }}, -1, -2147483648));
atlas.put("/activity/WebViewActivity", RouteMeta.build(RouteType.ACTIVITY, WebViewActivity.class, "/activity/webviewactivity", "activity", null, -1, -2147483648));
}
}

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
final class LogisticsCenter {
/**
* Completion the postcard by route metas
*
* @param postcard Incomplete postcard, should completion by this method.
*/
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");
}
//从仓库中获取路由信息
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) { // Maybe its does't exist, or didn't load.
//导入改路由分组信息
Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); // Load route meta.
if (null == groupMeta) {
throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
// Load route and cache it into memory, then delete from metas.
try {
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
}
//从缓存中读取该分组的路由信息
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());

if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
}
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}

completion(postcard); // Reload
}
} else {
//将路由信息导入到卡片中
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());

Uri rawUri = postcard.getUri();
if (null != rawUri) { // Try to set params into bundle.
Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
Map<String, Integer> paramsType = routeMeta.getParamsType();
//初始化跳转协议中的参数信息
if (MapUtils.isNotEmpty(paramsType)) {
// Set value by its type, just for params which annotation by @Param
for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
setValue(postcard,
params.getValue(),
params.getKey(),
resultMap.get(params.getKey()));
}

// Save params name which need auto inject.
postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
}

// Save raw uri
postcard.withString(ARouter.RAW_URI, rawUri.toString());
}

switch (routeMeta.getType()) {
case PROVIDER: // if the route is provider, should find its instance
// Its provider, so it must be implememt IProvider
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
IProvider provider;
try {
//通过反射构造Provider
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
//缓存provider路由信息
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}
}

DegradeService(降级容错服务)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Route(path = DegradeServiceImpl.PATH)
public class DegradeServiceImpl implements DegradeService {
public static final String PATH = "/service/DegradeServiceImpl";
@Override
public void onLost(Context context, Postcard postcard) {
if (context != null && postcard.getGroup().equals("activity")) {
ActivityCompat.startActivity(context, new Intent(context, DefalutActivity.class), null);
}

}

@Override
public void init(Context context) {

}
}

路由寻址出现问题的时候的容错处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
final class _ARouter {
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
/***********部分代码省略************/
if (null != callback) {
callback.onLost(postcard);
} else { // No callback for this invoke, then we use the global degrade service.
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}

return null;
}
/***********部分代码省略************/
}
}

PathReplaceService

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
@Route(path = PathReplaceServiceImpl.PATH)
public class PathReplaceServiceImpl implements PathReplaceService {
public static final String PATH = "/ddservice/PathReplaceServiceImpl";
private Map<String, String> pathMap;
@Override
public String forString(String path) {
String result = pathMap.containsKey(path) ? pathMap.get(path) : path;
return result;
}

@Override
public Uri forUri(Uri uri) {
return uri;
}

public void replacePath(String sourcePath, String targetPath) {
pathMap.put(sourcePath, targetPath);
}

@Override
public void init(Context context) {
pathMap = new HashMap<>();
}

public Map<String, String> getReplacePathMap() {
return Collections.unmodifiableMap(pathMap);
}
}

从定义的类名我们可以看出来就是替换路径的服务,在构造路由协议的时候首先都会使用PathReplaceService服务进行地址替换。

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
final class _ARouter {
/**
* Build postcard by path and default group
*/
protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
return build(path, extractGroup(path));
}
}

/**
* Build postcard by uri
*/
protected Postcard build(Uri uri) {
if (null == uri || TextUtils.isEmpty(uri.toString())) {
throw new HandlerException(Consts.TAG + "Parameter invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
uri = pService.forUri(uri);
}
return new Postcard(uri.getPath(), extractGroup(uri.getPath()), uri, null);
}
}
}

Interceptor拦截器

在ARouter模块的时候讲述Interceptor的使用,如果本次路由跳转不是走的绿色通道那么则会触发拦截器进行过滤。

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
final class _ARouter {
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
/************部分代码省略************/

if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
/**
* Continue process
*
* @param postcard route meta
*/
@Override
public void onContinue(Postcard postcard) {
_navigation(context, postcard, requestCode, callback);
}

/**
* Interrupt process, pipeline will be destory when this method called.
*
* @param exception Reson of interrupt.
*/
@Override
public void onInterrupt(Throwable exception) {
if (null != callback) {
callback.onInterrupt(postcard);
}

logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {
return _navigation(context, postcard, requestCode, callback);
}

return null;
}
}

拦截器的初始化

InterceptorServiceImpl的构造时间:

1
2
3
4
5
6
final class _ARouter {
static void afterInit() {
// Trigger interceptor init, use byName.
interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
}
}

InterceptorServiceImpl的init方法:

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
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
@Override
public void init(final Context context) {
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
//循环遍历仓库中的拦截器
for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
Class<? extends IInterceptor> interceptorClass = entry.getValue();
try {
//反射机制构造自定义的每一个拦截器实例
IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
iInterceptor.init(context);
//并将其添加在缓存中
Warehouse.interceptors.add(iInterceptor);
} catch (Exception ex) {
throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
}
}

interceptorHasInit = true;

logger.info(TAG, "ARouter interceptors init over.");

synchronized (interceptorInitLock) {
interceptorInitLock.notifyAll();
}
}
}
});
}
}

拦截器的工作过程

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
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) {
//检测是否初始化完所有的烂机器
checkInterceptorsInitStatus();
//没有完成正常的初始化,抛异常
if (!interceptorHasInit) {
callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
return;
}
//顺序遍历每一个拦截器,
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
try {
_excute(0, interceptorCounter, postcard);
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
//拦截器的遍历终止之后,如果有还有没有遍历的拦截器,则表示路由事件被拦截
if (interceptorCounter.getCount() > 0) { // Cancel the navigation this time, if it hasn't return anythings.
callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
} else if (null != postcard.getTag()) { // Maybe some exception in the tag.
callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
} else {
callback.onContinue(postcard);
}
} catch (Exception e) {
callback.onInterrupt(e);
}
}
});
} else {
callback.onContinue(postcard);
}
}

//执行拦截器的过滤事件
private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
if (index < Warehouse.interceptors.size()) {
IInterceptor iInterceptor = Warehouse.interceptors.get(index);
iInterceptor.process(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
// Last interceptor excute over with no exception.
counter.countDown();
//如果当前没有拦截过滤,那么使用下一个拦截器
_excute(index + 1, counter, postcard); // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
}

@Override
public void onInterrupt(Throwable exception) {
// Last interceptor excute over with fatal exception.
postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup.
counter.cancel();
}
});
}
}
}

Autowired的数据传输和自动注入

将数据放入intent中,然后getintent获取赋值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ParamsCallActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;

@Override
public void inject(Object target) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
ParamsCallActivity substitute = (ParamsCallActivity)target;
substitute.name = substitute.getIntent().getStringExtra("name");
substitute.age = substitute.getIntent().getIntExtra("age", substitute.age);
substitute.boy = substitute.getIntent().getBooleanExtra("girl", substitute.boy);
if (null != serializationService) {
substitute.obj = serializationService.parseObject(substitute.getIntent().getStringExtra("obj"), new com.alibaba.android.arouter.facade.model.TypeWrapper<Person>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'obj' in class 'ParamsCallActivity' , then you should implement 'SerializationService' to support object auto inject!");
}
}
}

数据类型转化

Postcard添加路由参数的时候都是放在Bundle中的,传递Object对象的时候是通过SerializationService服务先将其转化为String类型,然后在获取的时候再进反序列化。

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
public class TypeUtils {
private Types types;
private Elements elements;
private TypeMirror parcelableType;
public TypeUtils(Types types, Elements elements) {
this.types = types;
this.elements = elements;
parcelableType = this.elements.getTypeElement(PARCELABLE).asType();
}

//将数据类型转化为int值
public int typeExchange(Element element) {
TypeMirror typeMirror = element.asType();

// Primitive
if (typeMirror.getKind().isPrimitive()) {
return element.asType().getKind().ordinal();
}

switch (typeMirror.toString()) {
case BYTE:
return TypeKind.BYTE.ordinal();
case SHORT:
return TypeKind.SHORT.ordinal();
case INTEGER:
return TypeKind.INT.ordinal();
case LONG:
return TypeKind.LONG.ordinal();
case FLOAT:
return TypeKind.FLOAT.ordinal();
case DOUBEL:
return TypeKind.DOUBLE.ordinal();
case BOOLEAN:
return TypeKind.BOOLEAN.ordinal();
case STRING:
return TypeKind.STRING.ordinal();
default: // Other side, maybe the PARCELABLE or OBJECT.
if (types.isSubtype(typeMirror, parcelableType)) { // PARCELABLE
return TypeKind.PARCELABLE.ordinal();
} else { // For others
return TypeKind.OBJECT.ordinal();
}
}
}
}

缓存的数据模板,用int值表示数据类型进行存储:

1
atlas.put("/activity/ParamsCallActivity", RouteMeta.build(RouteType.ACTIVITY, ParamsCallActivity.class, "/activity/paramscallactivity", "activity", new java.util.HashMap<String, Integer>(){{put("obj", 10); put("name", 8); put("girl", 0); put("age", 3); }}, -1, -2147483648));

编译时的注解过程中执行数据获取:

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
@AutoService(Processor.class)
@SupportedOptions(KEY_MODULE_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
public class AutowiredProcessor extends AbstractProcessor {
private String buildStatement(String originalValue, String statement, int type, boolean isActivity) {
if (type == TypeKind.BOOLEAN.ordinal()) {
statement += (isActivity ? ("getBooleanExtra($S, " + originalValue + ")") : ("getBoolean($S)"));
} else if (type == TypeKind.BYTE.ordinal()) {
statement += (isActivity ? ("getByteExtra($S, " + originalValue + "") : ("getByte($S)"));
} else if (type == TypeKind.SHORT.ordinal()) {
statement += (isActivity ? ("getShortExtra($S, " + originalValue + ")") : ("getShort($S)"));
} else if (type == TypeKind.INT.ordinal()) {
statement += (isActivity ? ("getIntExtra($S, " + originalValue + ")") : ("getInt($S)"));
} else if (type == TypeKind.LONG.ordinal()) {
statement += (isActivity ? ("getLongExtra($S, " + originalValue + ")") : ("getLong($S)"));
}else if(type == TypeKind.CHAR.ordinal()){
statement += (isActivity ? ("getCharExtra($S, " + originalValue + ")") : ("getChar($S)"));
} else if (type == TypeKind.FLOAT.ordinal()) {
statement += (isActivity ? ("getFloatExtra($S, " + originalValue + ")") : ("getFloat($S)"));
} else if (type == TypeKind.DOUBLE.ordinal()) {
statement += (isActivity ? ("getDoubleExtra($S, " + originalValue + ")") : ("getDouble($S)"));
} else if (type == TypeKind.STRING.ordinal()) {
statement += (isActivity ? ("getStringExtra($S)") : ("getString($S)"));
} else if (type == TypeKind.PARCELABLE.ordinal()) {
statement += (isActivity ? ("getParcelableExtra($S)") : ("getParcelable($S)"));
} else if (type == TypeKind.OBJECT.ordinal()) {
statement = "serializationService.parseObject(substitute." + (isActivity ? "getIntent()." : "getArguments().") + (isActivity ? "getStringExtra($S)" : "getString($S)") + ", new com.alibaba.android.arouter.facade.model.TypeWrapper<$T>(){}.getType())";
}

return statement;
}
}

多dex的支持

可查看multidex源码:

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
public class ClassUtils {  
/**
* Identifies if the current VM has a native support for multidex, meaning there is no need for
* additional installation by this library.
*
* @return true if the VM handles multidex
*/
private static boolean isVMMultidexCapable() {
boolean isMultidexCapable = false;
String vmName = null;

try {
if (isYunOS()) { // YunOS需要特殊判断
vmName = "'YunOS'";
isMultidexCapable = Integer.valueOf(System.getProperty("ro.build.version.sdk")) >= 21;
} else { // 非YunOS原生Android
vmName = "'Android'";
String versionString = System.getProperty("java.vm.version");
if (versionString != null) {
Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString);
if (matcher.matches()) {
try {
int major = Integer.parseInt(matcher.group(1));
int minor = Integer.parseInt(matcher.group(2));
isMultidexCapable = (major > VM_WITH_MULTIDEX_VERSION_MAJOR)
|| ((major == VM_WITH_MULTIDEX_VERSION_MAJOR)
&& (minor >= VM_WITH_MULTIDEX_VERSION_MINOR));
} catch (NumberFormatException ignore) {
// let isMultidexCapable be false
}
}
}
}
} catch (Exception ignore) {

}

Log.i(Consts.TAG, "VM with name " + vmName + (isMultidexCapable ? " has multidex support" : " does not have multidex support"));
return isMultidexCapable;
}
}

InstantRun支持

在自己运行过程中,貌似InstantRun是不生效的。com.android.tools.fd.runtime.Paths这个类是不存在的。

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
public class ClassUtils {  
/**
* Get instant run dex path, used to catch the branch usingApkSplits=false.
*/
private static List<String> tryLoadInstantRunDexFile(ApplicationInfo applicationInfo) {
List<String> instantRunSourcePaths = new ArrayList<>();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && null != applicationInfo.splitSourceDirs) {
// add the split apk, normally for InstantRun, and newest version.
instantRunSourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
Log.d(Consts.TAG, "Found InstantRun support");
} else {
try {
// This man is reflection from Google instant run sdk, he will tell me where the dex files go.
Class pathsByInstantRun = Class.forName("com.android.tools.fd.runtime.Paths");
Method getDexFileDirectory = pathsByInstantRun.getMethod("getDexFileDirectory", String.class);
String instantRunDexPath = (String) getDexFileDirectory.invoke(null, applicationInfo.packageName);

File instantRunFilePath = new File(instantRunDexPath);
if (instantRunFilePath.exists() && instantRunFilePath.isDirectory()) {
File[] dexFile = instantRunFilePath.listFiles();
for (File file : dexFile) {
if (null != file && file.exists() && file.isFile() && file.getName().endsWith(".dex")) {
instantRunSourcePaths.add(file.getAbsolutePath());
}
}
Log.d(Consts.TAG, "Found InstantRun support");
}

} catch (Exception e) {
Log.e(Consts.TAG, "InstantRun support error, " + e.getMessage());
}
}

return instantRunSourcePaths;
}
}

总结

整个ARouter没有多少东西,但是值得我们学习的却有很多。框架对整个路由功能的模块划分以及像拦截器、降级处理、替换路径以及分组加载等。

RouterHelper GitHub地址

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦~!~!

想阅读作者的更多文章,可以查看我 个人博客 和公共号:

振兴书城
坚持原创技术分享,您的支持将鼓励我继续创作!