在組件化的時(shí)候漾橙,組件與組件是高度解耦的远舅,但組件與組件之間需要通信,這不得不提到ARouter
說在前面
// Cache route and metas
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>(); // 添加注解后將映射關(guān)系添加到這個(gè)集合當(dāng)中
static Map<String, RouteMeta> routes = new HashMap<>(); // 跳轉(zhuǎn)某個(gè)路由后的緩存悟泵,包括常用的Activity,Framgent,清單文件的meta
// Cache provider
static Map<Class, IProvider> providers = new HashMap<>(); // 實(shí)現(xiàn)IProvider的注解后映射關(guān)系添加到這個(gè)集合中
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]"); // 實(shí)現(xiàn)IInterceptor的注解映射關(guān)系添加到這個(gè)集合中
static List<IInterceptor> interceptors = new ArrayList<>(); // IInterceptor的緩存
分析目標(biāo)
若需要對Activity路由,只需要添加@Route闪水,如
@Route(path = "/test/activity2")
當(dāng)添加注解后糕非,會通過apt生成ARouter%Group%test的文件,里面包含有需要路由的相關(guān)的信息,包含一個(gè)RouteType枚舉類球榆,如
atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test"));
RouteType是一個(gè)枚舉朽肥,枚舉了如下:
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,接口實(shí)現(xiàn)類IProvider
案例分析
ARouter.init(getApplication())
ARouter.getInstance().build("/test/activity2").navigation();
這兩行代碼發(fā)生了什么事情
首先看init方法
public static void init(Application application) {
if (!hasInit) {
hasInit = _ARouter.init(application);
if (hasInit) {
_ARouter.afterInit();
}
}
}
hasInit默認(rèn)為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 {
...
}
}
我調(diào)試發(fā)現(xiàn)registerByPlugin = true持钉,只是打印了一個(gè)log
這里是將hasInit設(shè)置為true衡招,代表初始化成功了,并返回true
接著會調(diào)用_ARouter.afterInit() 這里是初始化一個(gè) PROVIDER每强,僅此而已
這里只是初始化了ARouter.init(getApplication()) 東西并不多
接著會路由跳轉(zhuǎn)始腾,在分析之前州刽,我先闡述下ARouter與_ARouter系,他們的關(guān)系是23種設(shè)計(jì)模式中的外觀模式浪箭,_ARouter是核心類穗椅,基本上所有的邏輯都在這里面,ARouter只是包了一層奶栖,做了下方法的傳遞
ARouter.getInstance().build("/test/activity2")
進(jìn)入到_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,接著調(diào)用build()
protected Postcard build(String path, String group, Boolean afterReplace) {
...
return new Postcard(path, group);
}
關(guān)鍵代碼只有 return new Postcard(path, group)宣鄙,而Postcard繼承的是RouteMeta,build()走完后桑孩,調(diào)用navigation()
public Object navigation(Context context, NavigationCallback callback) {
return ARouter.getInstance().navigation(context, this, -1, callback);
}
由于ARouter和_ARouter是外觀設(shè)計(jì)模式,直接看_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行代碼又是一個(gè)攔截流椒,由于沒有實(shí)現(xiàn),這里忽略明也,看第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(第一次調(diào)用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后再調(diào)用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!");
}
}
// 將實(shí)例對象放在postcard中
postcard.setProvider(instance);
postcard.greenChannel();
break;
case FRAGMENT:
postcard.greenChannel();
default:
break;
}
這里做了一些賦值操作,如果是PROVIDER且providers緩存集合里沒有時(shí)冕屯,通過返回獲取實(shí)例以后會調(diào)用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);
}
這里是調(diào)用了攔截器安聘,若注解了攔截器痰洒,會先走攔截器里實(shí)現(xiàn)的邏輯,在調(diào)用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,則跳轉(zhuǎn)到activity,
若是PROVIDER,則返回IProvider對象褂痰,
若是BOARDCAST,CONTENT_PROVIDER泉粉,F(xiàn)RAGMENT,則返回Fragment對象
總結(jié)
若是路由的是Activity舍肠,則直接跳轉(zhuǎn)到指定的Activity,若是其他的搀继,則獲取實(shí)例后進(jìn)行其他邏輯的處理