在组件化的时候,组件与组件是高度解耦的,但组件与组件之间需要通信,这不得不提到ARouter
说在前面
ARouter.png// Cache route and metas
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>(); // 添加注解后将映射关系添加到这个集合当中
static Map<String, RouteMeta> routes = new HashMap<>(); // 跳转某个路由后的缓存,包括常用的Activity,Framgent,清单文件的meta
// Cache provider
static Map<Class, IProvider> providers = new HashMap<>(); // 实现IProvider的注解后映射关系添加到这个集合中
static Map<String, RouteMeta> providersIndex = new HashMap<>(); // IProvider的缓存
// Cache interceptor
static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]"); // 实现IInterceptor的注解映射关系添加到这个集合中
static List<IInterceptor> interceptors = new ArrayList<>(); // IInterceptor的缓存
分析目标
若需要对Activity路由,只需要添加@Route,如
@Route(path = "/test/activity2")
当添加注解后,会通过apt生成ARouter%Group%test的文件,里面包含有需要路由的相关的信息,包含一个RouteType枚举类,如
atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test"));
RouteType是一个枚举,枚举了如下:
ACTIVITY(0, "android.app.Activity"),
SERVICE(1, "android.app.Service"),
PROVIDER(2, "com.alibaba.android.arouter.facade.template.IProvider"),
CONTENT_PROVIDER(-1, "android.app.ContentProvider"),
BOARDCAST(-1, ""),
METHOD(-1, ""),
FRAGMENT(-1, "android.app.Fragment"),
UNKNOWN(-1, "Unknown route type");
常见的有Activity,Fragment,接口实现类IProvider
案例分析
ARouter.init(getApplication())
ARouter.getInstance().build("/test/activity2").navigation();
这两行代码发生了什么事情
首先看init方法
public static void init(Application application) {
if (!hasInit) {
hasInit = _ARouter.init(application);
if (hasInit) {
_ARouter.afterInit();
}
}
}
hasInit默认为false
protected static synchronized boolean init(Application application) {
mContext = application;
LogisticsCenter.init(mContext, executor);
hasInit = true;
mHandler = new Handler(Looper.getMainLooper());
return true;
}
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
if (registerByPlugin) {
logger.info(TAG, "Load router map by arouter-auto-register plugin.");
} else {
...
}
}
我调试发现registerByPlugin = true,只是打印了一个log
这里是将hasInit设置为true,代表初始化成功了,并返回true
接着会调用_ARouter.afterInit() 这里是初始化一个 PROVIDER,仅此而已
这里只是初始化了ARouter.init(getApplication()) 东西并不多
接着会路由跳转,在分析之前,我先阐述下ARouter与_ARouter系,他们的关系是23种设计模式中的外观模式,_ARouter是核心类,基本上所有的逻辑都在这里面,ARouter只是包了一层,做了下方法的传递
ARouter.getInstance().build("/test/activity2")
进入到_ARouter.build()里
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), true);
}
}
第5行是对path做处理,由于没有添加注解,pService=null,接着调用build()
protected Postcard build(String path, String group, Boolean afterReplace) {
...
return new Postcard(path, group);
}
关键代码只有 return new Postcard(path, group),而Postcard继承的是RouteMeta,build()走完后,调用navigation()
public Object navigation(Context context, NavigationCallback callback) {
return ARouter.getInstance().navigation(context, this, -1, callback);
}
由于ARouter和_ARouter是外观设计模式,直接看_ARouter的navigation
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;
}
// Set context to postcard.
postcard.setContext(null == context ? mContext : context);
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(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(postcard, requestCode, callback);
}
return null;
}
第2,3行代码又是一个拦截,由于没有实现,这里忽略,看第12行代码LogisticsCenter.completion(postcard);
public synchronized static void completion(Postcard postcard) {
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
// Load route and cache it into memory, then delete from metas.
addRouteGroupDynamic(postcard.getGroup(), null);
completion(postcard); // Reload
} else {
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
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) {
logger.error(TAG, "Init provider failed!", e);
throw new HandlerException("Init provider failed!");
}
}
postcard.setProvider(instance);
postcard.greenChannel(); // Provider should skip all of interceptors
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment needn't interceptors
default:
break;
}
}
}
if 和 else里做的事情是,如果缓存中没有指定的path(第一次调用group),则走if,去解析,else 则做赋值等操作,
public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) {
if (Warehouse.groupsIndex.containsKey(groupName)){
Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(groupName);
}
// cover old group.
if (null != group) {
group.loadInto(Warehouse.routes);
}
}
第3行是通过group在groupsIndex中获取class,groupsIndex是@Route注解后添加到集合的,通过反射获取对象后,将相同的group放到routes集合里,放到routes后再调用completion,则走 else
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
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) {
logger.error(TAG, "Init provider failed!", e);
throw new HandlerException("Init provider failed!");
}
}
// 将实例对象放在postcard中
postcard.setProvider(instance);
postcard.greenChannel();
break;
case FRAGMENT:
postcard.greenChannel();
default:
break;
}
这里做了一些赋值操作,如果是PROVIDER且providers缓存集合里没有时,通过返回获取实例以后会调用init()方法,并将对象放到providers缓存集合中
至此,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(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(postcard, requestCode, callback);
}
这里是调用了拦截器,若注解了拦截器,会先走拦截器里实现的逻辑,在调用onContinue方法的_navigation方法
private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = postcard.getContext();
switch (postcard.getType()) {
case ACTIVITY:
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras());
...
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;
}
若是ACTIVITY,则跳转到activity,
若是PROVIDER,则返回IProvider对象,
若是BOARDCAST,CONTENT_PROVIDER,FRAGMENT,则返回Fragment对象
总结
若是路由的是Activity,则直接跳转到指定的Activity,若是其他的,则获取实例后进行其他逻辑的处理
网友评论