ARouteralibaba开源的组件化开发框架,在之前开发项目中也用到了,今天就来大致分析下其功能的流,这里以分析创建Provider为例。
首先我们在base模块中定义了一个Factory获取Proivder

1
2
3
4
5
6
7
8
9
10
public class ModuleProviderFactory {

/**
* 获取模块Provider
*/
public static <T extends IProvider> T getModuleProvider(String providerName) {
return (T) ARouter.getInstance().build(providerName).navigation();
}

}

以及为不同的 module 创建了Provider,这些Provider中定义了需要实现的行为

1
2
3
public interface IModuleAProvider extends IProvider {
String sayHello(String name);
}

上面这个是ModuleAProvider,我们来看看ModuleA中的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
@Route(path = ProviderPath.PROVIDE_MODULEA)
public class ModuleAProvider implements IModuleAProvider {

@Override
public void init(Context context) {

}

@Override
public String sayHello(String name) {
return null;
}
}

ProviderPath中定义了Provider的获取路径,在base模块中创建,假如在另一个ModuleB想调用ModuleA暴露出来的接口,就可以如下方式

1
2
IModuleAProvider iModuleAProvider = ModuleProviderFactory.getModuleProvider(ProviderPath.PROVIDE_MODULEA);
iModuleAProvider.sayHello("");

iModuleAProvider指向通过调用ARouter.getInstance().build(providerName).navigation()返回的实例,我们先来看其初始化流程,在Application中我们会调用ARouter.init(this);

1
2
3
4
5
6
7
8
9
10
11
12
13
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.init(application);方法

1
2
3
4
5
6
7
8
9
protected static synchronized boolean init(Application application) {
mContext = application;
LogisticsCenter.init(mContext, executor);
logger.info(Consts.TAG, "ARouter init success!");
hasInit = true;
mHandler = new Handler(Looper.getMainLooper());

return true;
}

这个方法中保存了application以及创建了一个主线程mHandler,以及调用LogisticsCenter.init(mContext, executor);

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
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
mContext = context;
executor = tpe;

//...此处省略部分代码
Set<String> routerMap;

// 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 generated by 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); // Save new version name when router map update finishes.
} 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>()));
}

//...此处省略部分代码

for (String className : routerMap) {
if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
// This one of root elements, load root.
((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
// Load interceptorMeta
((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
} else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
// Load providerIndex
((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
}
}
//...此处省略部分代码
}

首先判断是否开启了Debug模式或者版本号是否有更新,两条件满足其一,则ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);这个方法会放在线程池中的子线程执行,就是获取到所有以com.alibaba.android.arouter.routes为头部的class路径(即通过编译时注解生成对应的 class 文件)的集合,如果不为空则保存到 SP 文件中,如果两个条件没一个满足的话,则会从 SP 中获取之前保存的集合。然后遍历集合,刷选出特定路径,获取到class实例通过构造器创建对象,调用loadInto方法,比如可以在/modulea/build/generated/ap_generated_sources/debug/out/com/alibaba/android/arouter/routes下找到符合该规则的ARouter$$Root$$modulea调用loadInto方法

1
2
3
4
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("modulea", ARouter$$Group$$modulea.class);
}

ARouter$$Group$$modulea也是编译生成的类,routesWarehouse.groupsIndex,接着看其内部

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();
}
}

这个类的作用就是用来存储的,像ARouter$$Group$$modulea.class就保存在groupsIndex中,至于ARouter$$Group$$modulea中的逻辑我们后面会看到,初始化流程就是如此了,接着我们来分析下ARouter.getInstance().build(providerName).navigation()
getInstance()方法会获取到ARouter的实例,下一步调用build(provideName)

1
2
3
public Postcard build(String path) {
return _ARouter.getInstance().build(path);
}

其实就是调用了_ARouter实例的build方法

1
2
3
4
5
6
7
8
9
10
11
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));
}
}

我们没有定义PathReplaceService,继续

1
2
3
4
5
6
7
8
9
10
11
protected Postcard build(String path, String group) {
if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
throw new HandlerException(Consts.TAG + "Parameter is invalid!");
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
return new Postcard(path, group);
}
}

extractGroup方法获取到的是第一对“/ ”之间的字串,代表着group名称,比如这里“/modulea/provider”中的modulea,最后会通过“/modulea/provider”和modulea创建一个Postcard实例,PostcardRouteMeta的子类,而RouteMeta保存的是路由的信息。ok得到这个实例之后调用了Postcardnavigation()方法

1
2
3
4
5
6
7
8
9
10
11
public Object navigation() {
return navigation(null);
}

public Object navigation(Context context) {
return navigation(context, null);
}

public Object navigation(Context context, NavigationCallback callback) {
return ARouter.getInstance().navigation(context, this, -1, callback);
}

最终调用ARouternavigation方法

1
2
3
public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
}

然后又回到了_ARouter调用

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

try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException ex) {
//...此处省略部分代码
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);
}

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

return null;
}

看看LogisticsCenter.completion(postcard);中的逻辑

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
public synchronized static void completion(Postcard postcard) {
//...此处省略部分代码

//根据完整路径获取 routeMeta 对象
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());

if (null == routeMeta) {
//如果没有获取到路由的缓存对象,那么获取缓存中在初始化的时候保存的 class 即 ARouter$$Group$$modulea
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 {
//...此处省略部分代码

//通过构造器创建 ARouter$$Group$$modulea 实例
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();

//把 IRouteGroup 实现类的实例中保存的路由信息放到 Warehouse 缓存中
//比如 ARouter$$Group$$modulea 中的
// atlas.put("/modulea/provider", RouteMeta.build(RouteType.PROVIDER, ModuleAProvider.class, "/modulea/provider", "modulea", null, -1, -2147483648));
iGroupInstance.loadInto(Warehouse.routes);

//移除对应 Group 的缓存,即 ARouter$$Group$$modulea
Warehouse.groupsIndex.remove(postcard.getGroup());

//...此处省略部分代码
} catch (Exception e) {
throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
}

//再次调用自身方法,此时路由信息已经不为空了,会走到下面的 else 里
completion(postcard); // Reload
}
} else {
// atlas.put("/modulea/provider", RouteMeta.build(RouteType.PROVIDER, ModuleAProvider.class, "/modulea/provider", "modulea", null, -1, -2147483648));
//routeMeta.getDestination()即ModuleAProvider.class
postcard.setDestination(routeMeta.getDestination());

//routeMeta.getType()即RouteType.PROVIDER类型
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 implement IProvider
//通过路由信息获取到 ModuleAProvider.class
Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
//第一次拿到的是 null
IProvider instance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this provider
IProvider provider;
try {
//通过 ModuleAProvider.class 的构造器创建实例
provider = providerMeta.getConstructor().newInstance();
//调用 ModuleAProvider 实例的 init 方法
provider.init(mContext);
//将 Provider 放入缓存中
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exception e) {
throw new HandlerException("Init provider failed! " + e.getMessage());
}
}
//将 ModuleAProvider 实例放入 postcard 路由信息中
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}

具体逻辑看代码注释了,大致就是编译生成的Group下的具体路径和路由信息放入Warehouse缓存中,如果没有则将路由信息放入缓存,并移除Group缓存,然后再一次调用自己,此时对应路径下已经有具体的路由信息了,此时会再将路由信息放入到传入参数postcard的路由信息中,如果是Provider类型,如果没有缓存还会创建实例设置到postcard,并放入Warehouse里缓存。
接下来调用 _navigation(context, postcard, requestCode, callback);

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
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = null == context ? mContext : context;

switch (postcard.getType()) {
case ACTIVITY:
// Build intent
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());

// Set flags.
int flags = postcard.getFlags();
if (-1 != flags) {
intent.setFlags(flags);
} else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}

// Set Actions
String action = postcard.getAction();
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
}

// Navigation in main looper.
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});

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.getType()PROVIDER类型的,所有直接返回了我们上一步在postcard中塞入创建的ModuleAProvider实例,接着就可以调用其sayHello方法了。
不难发现,其实在ARouterGroup的划分是以路径中第一对“/”中的字串作为基准的,一开始会将根据不同Group生成的ARouter$$Group$$字串的 class 放入Warehouse中缓存,然后根据调用的 path 将不同Group的具体路径对应的具体路由加载进Warehouse,再获取对应的RouteMeta路由信息,重新组装到postcard中,最后调用_navigation根据postcard不同的类型执行相应的逻辑。还有一点非常明显,当我们调用ARouter的方法的时候最终都会交由_ARouter去执行,这里用到的是结构性设计模式中的外观模式。
大致分析就是如此了。