ARouter初始化及跳转原理
Posted ImportSUC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARouter初始化及跳转原理相关的知识,希望对你有一定的参考价值。
ARouter初始化及跳转原理
编译后生成文件
仓库类
``
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<>();
//省略部分代码
1.初始化代码追踪
ARouter.init(this);
进入ARouter.java
进入__ARouter.java
进入LogisticsCenter.java
``
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.
//如果是debug模式,或者是新版本,则更新,否则直接从sp中获取
if (ARouter.debuggable() || PackageUtils.isNewVersion(context))
//关键代码1:获取“com.alibaba.android.arouter.routes”包名下的所有的class类名
//“com.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 finishes.
else
routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
//进行实例化,只针对Root,Interceptor,provider
for (String className : routerMap)
//com.alibaba.android.arouter.routes$$.ARouter$$Root
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);
1.首先通过包名获取包名下的class类名
2.反射进行实例化后,跳用loadInto,进行数据加载,将数据保存到Warehouse.groupsIndex
``
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Root$$app implements IRouteRoot
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
routes.put("demo", ARouter$$Group$$demo.class);
routes.put("uri", ARouter$$Group$$uri.class);
END
跳转
ARouter.getInstance().build(RouteConstant.LOGIN)
.withString(LoginActivity.KEY_PATH, postcard.getPath())
.navigation();
1.build
``
/**
* 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));
如果有PathReplaceService,则进行路径替换。所以我们可以在项目中继承PathReplaceService来实现路径替换
``
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);
//关键代码 :创建Postcard对象。Postcard对象中包含了跳转所需要的class对象,参数等必须元素,此处只是设置了Postcard的path和group,其他属性的设置在navigation中完成
return new Postcard(path, group);
2.navigation
Postcard.java
``
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);
ARouter.java
``
public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback)
return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
_ARouter.java
``
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback)
//预处理服务
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard))
// Pretreatment failed, navigation canceled.
return null;
try
//关键代码,对postcard剩余字段进行赋值
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);
//greenChannel = true 时拦截器不工作,eg: fragment 的greenChannel 为true
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;
LogisiticsCenter.java
``
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.拿到group的class对象
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
//省略代码
/********************关键代码****************/
//通过class对象进行初始化
IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
//将要跳转的activity roteMeta数据加载到Warehouse.routes
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
//省略代码
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 implement 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 = providerMeta.getConstructor().newInstance();
provider.init(mContext);
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;
``
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()
以上是关于ARouter初始化及跳转原理的主要内容,如果未能解决你的问题,请参考以下文章