You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
publicclassRouteMeta {
privateRouteTypetype; // Type of routeprivateElementrawType; // Raw type of routeprivateClass<?> destination; // DestinationprivateStringpath; // Path of routeprivateStringgroup; // Group of routeprivateintpriority = -1; // The smaller the number, the higher the priorityprivateintextra; // Extra dataprivateMap<String, Integer> paramsType; // Param typeprivateStringname;
privateMap<String, Autowired> injectConfig; // Cache inject config.
// 包含路由表的数据结构, 附加一些跳转信息,如参数之类publicfinalclassPostcardextendsRouteMeta {
// BaseprivateUriuri;
privateObjecttag; // A tag prepare for some thing wrong.privateBundlemBundle; // Data to transformprivateintflags = -1; // Flags of routeprivateinttimeout = 300; // Navigation timeout, TimeUnit.SecondprivateIProviderprovider; // It will be set value, if this postcard was provider.privatebooleangreenChannel;
privateSerializationServiceserializationService;
// AnimationprivateBundleoptionsCompat; // The transition animation of activityprivateintenterAnim = -1;
privateintexitAnim = -1;
// 通过路由基本信息完善 PostCardpublicsynchronizedstaticvoidcompletion(Postcardpostcard) {
RouteMetarouteMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) { // Maybe its does't exist, or didn't load.Class<? extendsIRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); // Load route meta.if (null == groupMeta) {
thrownewNoRouteFoundException(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()));
}
IRouteGroupiGroupInstance = 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 (Exceptione) {
thrownewHandlerException(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());
UrirawUri = 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 @Paramfor (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(newString[]{}));
}
// Save raw uripostcard.withString(ARouter.RAW_URI, rawUri.toString());
}
switch (routeMeta.getType()) {
casePROVIDER: // if the route is provider, should find its instance// Its provider, so it must implement IProviderClass<? extendsIProvider> providerMeta = (Class<? extendsIProvider>) routeMeta.getDestination();
IProviderinstance = Warehouse.providers.get(providerMeta);
if (null == instance) { // There's no instance of this providerIProviderprovider;
try {
provider = providerMeta.getConstructor().newInstance();
provider.init(mContext);
Warehouse.providers.put(providerMeta, provider);
instance = provider;
} catch (Exceptione) {
thrownewHandlerException("Init provider failed! " + e.getMessage());
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptorsbreak;
caseFRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptorsdefault:
break;
}
}
总结
基本的流程分析结束,后续会继续分析 apt 的相关使用。
The text was updated successfully, but these errors were encountered:
Uh oh!
There was an error while loading. Please reload this page.
Arouter
[TOC]
需求背景
当一个 App 开发随着迭代而变得复杂时,多模块开发就显的很有必要,multimodule。
Android 原生方案的不足
原生路由方案一般是通过显式 intent 和隐式 intent 两种方式实现,均存在不足:
自定义路由框架的适用场景
Arouter 概述
优点请参考官方文档:https://github.com/alibaba/ARouter/blob/master/README_CN.md
源码分析
直接从 github 官方仓库下载源码编译即可。
其中 app, module_java, module_kotlin, 是 demo 演示;arouter_annotation 包含注解数据和携带数据的bean;arouter_compiler 是注解处理相关,后面会专门介绍编译时代码生成相关的内容。比如该 demo 就在 build 目录下生成了 Arouter 相关的代码。
arouter-api 提供了给我们使用的api,以实现路由功能。
init
上述函数是将注解生成的路由表信息,拦截器信息和 Provider 信息存到缓存中。
下面接着看一下生成的实现类做了什么工作:
IRouteRoot的实现将有@route注解的module名添加到参数集合中,也就是groupsIndex。
官方的建议是路径分组与模块名相同,并且不同模块不要使用相同的分组。
上面的 RouteMeta 是一个数据 bean,封装了注解的相关内容;
Init 方法的内容大概如下, 还有一个 initAfter 方法。
根据官方的说明,IProvider接口是用来暴露服务,并且在初始化的时候会被调用
init(Context context)
方法。具体的服务有其实现提供,那我们就来看下它的实现做了些什么:还记的在上一步初始化的时候将所有注解了Interceptor的类的信息存入了Warehouse.interceptorsIndex,这里就将这些类实例化,并调用
iInterceptor.init(context);
完成自定义的初始化内容,最后放入Warehouse.interceptors集合中。总结来说,init过程就是把所有注解的信息加载内存中,并且完成所有拦截器的初始化。
navagation
最后的 _navigation 过程很简单。
整个路由跳转的过程大致完成,整个过程可以分为:封装Postcard -> 查找信息集合,实例化目标类 -> 返回实例或者跳转。
上述的过程加遗漏了一个方法,这里分析一下:
总结
基本的流程分析结束,后续会继续分析 apt 的相关使用。
The text was updated successfully, but these errors were encountered: