//RouteProcessor的parseRoutes方法//遍历所有元素for(Elementelement:routeElements){TypeMirrortm=element.asType();//获取注解Routeroute=element.getAnnotation(Route.class);RouteMetarouteMeta;// Activity or Fragment//判断注解作用的类,是否是Activity或者Fragment的子类if(types.isSubtype(tm,type_Activity)||types.isSubtype(tm,fragmentTm)||types.isSubtype(tm,fragmentTmV4)){// Get all fields annotation by @AutowiredMap<String,Integer>paramsType=newHashMap<>();Map<String,Autowired>injectConfig=newHashMap<>();injectParamCollector(element,paramsType,injectConfig);//如果是Activityif(types.isSubtype(tm,type_Activity)){// Activitylogger.info(">>> Found activity route: "+tm.toString()+" <<<");routeMeta=newRouteMeta(route,element,RouteType.ACTIVITY,paramsType);}else{//若果是Fragment// Fragmentlogger.info(">>> Found fragment route: "+tm.toString()+" <<<");routeMeta=newRouteMeta(route,element,RouteType.parse(FRAGMENT),paramsType);}routeMeta.setInjectConfig(injectConfig);}elseif(types.isSubtype(tm,iProvider)){// IProviderlogger.info(">>> Found provider route: "+tm.toString()+" <<<");routeMeta=newRouteMeta(route,element,RouteType.PROVIDER,null);}elseif(types.isSubtype(tm,type_Service)){// Servicelogger.info(">>> Found service route: "+tm.toString()+" <<<");routeMeta=newRouteMeta(route,element,RouteType.parse(SERVICE),null);}else{thrownewRuntimeException("The @Route is marked on unsupported class, look at ["+tm.toString()+"].");}categories(routeMeta);}
privatevoidcategories(RouteMetarouteMete){//校验if(routeVerify(routeMete)){logger.info(">>> Start categories, group = "+routeMete.getGroup()+", path = "+routeMete.getPath()+" <<<");Set<RouteMeta>routeMetas=groupMap.get(routeMete.getGroup());//如果是空则创建Set,并将routeMeta添加到Set中,最后将Set添加到Map中if(CollectionUtils.isEmpty(routeMetas)){//创建TreeSet保持有序Set<RouteMeta>routeMetaSet=newTreeSet<>(newComparator<RouteMeta>(){@Overridepublicintcompare(RouteMetar1,RouteMetar2){try{returnr1.getPath().compareTo(r2.getPath());}catch(NullPointerExceptionnpe){logger.error(npe.getMessage());return0;}}});routeMetaSet.add(routeMete);groupMap.put(routeMete.getGroup(),routeMetaSet);}else{routeMetas.add(routeMete);}}else{logger.warning(">>> Route meta verify error, group is "+routeMete.getGroup()+" <<<");}}
privatebooleanrouteVerify(RouteMetameta){Stringpath=meta.getPath();//如果path是空或者不是以/开头直接返回false//这里设计是否可以优化一下呢?能否在编译时报错,而不是到运行时才校验?if(StringUtils.isEmpty(path)||!path.startsWith("/")){// The path must be start with '/' and not empty!returnfalse;}//如果Group是空,则截取第一个/和第二个/之间的字符串为Groupif(StringUtils.isEmpty(meta.getGroup())){// Use default group(the first word in path)try{StringdefaultGroup=path.substring(1,path.indexOf("/",1));logger.info("routeVerify path"+path);logger.info("routeVerify "+defaultGroup);if(StringUtils.isEmpty(defaultGroup)){returnfalse;}meta.setGroup(defaultGroup);returntrue;}catch(Exceptione){logger.error("Failed to extract default group! "+e.getMessage());returnfalse;}}returntrue;}
//遍历HashMapfor(Map.Entry<String,Set<RouteMeta>>entry:groupMap.entrySet()){StringgroupName=entry.getKey();//loadInto方法MethodSpec.BuilderloadIntoMethodOfGroupBuilder=MethodSpec.methodBuilder(METHOD_LOAD_INTO).addAnnotation(Override.class).addModifiers(PUBLIC).addParameter(groupParamSpec);List<RouteDoc>routeDocList=newArrayList<>();// Build group method body//获取相同Group的RouteMetaSet<RouteMeta>groupData=entry.getValue();for(RouteMetarouteMeta:groupData){//将RouteMeta映射为RouteDocRouteDocrouteDoc=extractDocInfo(routeMeta);ClassNameclassName=ClassName.get((TypeElement)routeMeta.getRawType());//如果是Providerswitch(routeMeta.getType()){casePROVIDER:// Need cache provider's super classList<?extendsTypeMirror>interfaces=((TypeElement)routeMeta.getRawType()).getInterfaces();for(TypeMirrortm:interfaces){routeDoc.addPrototype(tm.toString());if(types.isSameType(tm,iProvider)){// Its implements iProvider interface himself.// This interface extend the IProvider, so it can be used for mark providerloadIntoMethodOfProviderBuilder.addStatement("providers.put($S, $T.build($T."+routeMeta.getType()+", $T.class, $S, $S, null, "+routeMeta.getPriority()+", "+routeMeta.getExtra()+"))",(routeMeta.getRawType()).toString(),routeMetaCn,routeTypeCn,className,routeMeta.getPath(),routeMeta.getGroup());}elseif(types.isSubtype(tm,iProvider)){// This interface extend the IProvider, so it can be used for mark providerloadIntoMethodOfProviderBuilder.addStatement("providers.put($S, $T.build($T."+routeMeta.getType()+", $T.class, $S, $S, null, "+routeMeta.getPriority()+", "+routeMeta.getExtra()+"))",tm.toString(),// So stupid, will duplicate only save class name.routeMetaCn,routeTypeCn,className,routeMeta.getPath(),routeMeta.getGroup());}}break;default:break;}// Make map body for paramsTypeStringBuildermapBodyBuilder=newStringBuilder();Map<String,Integer>paramsType=routeMeta.getParamsType();Map<String,Autowired>injectConfigs=routeMeta.getInjectConfig();if(MapUtils.isNotEmpty(paramsType)){List<RouteDoc.Param>paramList=newArrayList<>();for(Map.Entry<String,Integer>types:paramsType.entrySet()){mapBodyBuilder.append("put(\"").append(types.getKey()).append("\", ").append(types.getValue()).append("); ");RouteDoc.Paramparam=newRouteDoc.Param();AutowiredinjectConfig=injectConfigs.get(types.getKey());param.setKey(types.getKey());param.setType(TypeKind.values()[types.getValue()].name().toLowerCase());param.setDescription(injectConfig.desc());param.setRequired(injectConfig.required());paramList.add(param);}routeDoc.setParams(paramList);}StringmapBody=mapBodyBuilder.toString();//方法loadIntoMethodOfGroupBuilder.addStatement("atlas.put($S, $T.build($T."+routeMeta.getType()+", $T.class, $S, $S, "+(StringUtils.isEmpty(mapBody)?null:("new java.util.HashMap<String, Integer>(){{"+mapBodyBuilder.toString()+"}}"))+", "+routeMeta.getPriority()+", "+routeMeta.getExtra()+"))",routeMeta.getPath(),routeMetaCn,routeTypeCn,className,routeMeta.getPath().toLowerCase(),routeMeta.getGroup().toLowerCase());routeDoc.setClassName(className.toString());routeDocList.add(routeDoc);}
@Target({ElementType.TYPE})@Retention(RetentionPolicy.CLASS)public@interfaceRoute{/** * Path of route */Stringpath();//路径/** * Used to merger routes, the group name MUST BE USE THE COMMON WORDS !!! */Stringgroup()default"";//group 如果不是设置会获取[1,indexOf(1,'/')]之间的字符串为group/** * Name of route, used to generate javadoc. */Stringname()default"";/** * Extra data, can be set by user. * Ps. U should use the integer num sign the switch, by bits. 10001010101010 */intextras()defaultInteger.MIN_VALUE;/** * The priority of route. */intpriority()default-1;}
publicclassRouteMeta{privateRouteTypetype;// Type of route 路由类型privateElementrawType;// 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;}
//AutowiredServiceImpl.java@Overridepublicvoidautowire(Objectinstance){doInject(instance,null);}privatevoiddoInject(Objectinstance,Class<?>parent){Class<?>clazz=null==parent?instance.getClass():parent;ISyringesyringe=getSyringe(clazz);if(null!=syringe){syringe.inject(instance);//调用辅助类的inject方法}//获取父类Class<?>superClazz=clazz.getSuperclass();// has parent and its not the class of framework.//父类不为空,且不是framework的类if(null!=superClazz&&!superClazz.getName().startsWith("android")){doInject(instance,superClazz);}}//获取运行时注解生成的辅助类privateISyringegetSyringe(Class<?>clazz){StringclassName=clazz.getName();try{if(!blackList.contains(className)){ISyringesyringeHelper=classCache.get(className);if(null==syringeHelper){// No cache.//类名$$ARouter$$AutowiredsyringeHelper=(ISyringe)Class.forName(clazz.getName()+SUFFIX_AUTOWIRED).getConstructor().newInstance();}classCache.put(className,syringeHelper);returnsyringeHelper;}}catch(Exceptione){blackList.add(className);// This instance need not autowired.}returnnull;}
/** * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. *///生成的KotlinTestActivity辅助类publicclassKotlinTestActivity$$ARouter$$AutowiredimplementsISyringe{privateSerializationServiceserializationService;@Overridepublicvoidinject(Objecttarget){serializationService=ARouter.getInstance().navigation(SerializationService.class);KotlinTestActivitysubstitute=(KotlinTestActivity)target;//调用KotlinTestActivity的getIntent获取参数substitute.name=substitute.getIntent().getExtras()==null?substitute.name:substitute.getIntent().getExtras().getString("name",substitute.name);substitute.age=substitute.getIntent().getIntExtra("age",substitute.age);}}
//调用_ARouter的build方法会返回一个Postcard对象,然后调用//postcard对象的protectedPostcardbuild(Stringpath){if(TextUtils.isEmpty(path)){thrownewHandlerException(Consts.TAG+"Parameter is invalid!");}else{//获取PathReplaceServicePathReplaceServicepService=ARouter.getInstance().navigation(PathReplaceService.class);if(null!=pService){path=pService.forString(path);}returnbuild(path,extractGroup(path),true);}}
protectedPostcardbuild(Stringpath,Stringgroup,BooleanafterReplace){if(TextUtils.isEmpty(path)||TextUtils.isEmpty(group)){thrownewHandlerException(Consts.TAG+"Parameter is invalid!");}else{if(!afterReplace){PathReplaceServicepService=ARouter.getInstance().navigation(PathReplaceService.class);if(null!=pService){path=pService.forString(path);}}//创建一个postcard对象returnnewPostcard(path,group);}}
//获取GroupprivateStringextractGroup(Stringpath){//如果不是以/开头,编译期可以通过编译只是不创建对应的类//如果是空或者不是以/开头 则直接抛出异常if(TextUtils.isEmpty(path)||!path.startsWith("/")){thrownewHandlerException(Consts.TAG+"Extract the default group failed, the path must be start with '/' and contain more than 2 '/'!");}try{StringdefaultGroup=path.substring(1,path.indexOf("/",1));if(TextUtils.isEmpty(defaultGroup)){thrownewHandlerException(Consts.TAG+"Extract the default group failed! There's nothing between 2 '/'!");}else{returndefaultGroup;}}catch(Exceptione){returnnull;}}
//_ARouter.javaprotectedObjectnavigation(finalContextcontext,finalPostcardpostcard,finalintrequestCode,finalNavigationCallbackcallback){//获取PretreatmentServicePretreatmentServicepretreatmentService=ARouter.getInstance().navigation(PretreatmentService.class);if(null!=pretreatmentService&&!pretreatmentService.onPretreatment(context,postcard)){// Pretreatment failed, navigation canceled.returnnull;}// Set context to postcard.postcard.setContext(null==context?mContext:context);try{//执行completionLogisticsCenter.completion(postcard);}catch(NoRouteFoundExceptionex){//执行失败回调if(null!=callback){callback.onLost(postcard);}else{// No callback for this invoke, then we use the global degrade service.DegradeServicedegradeService=ARouter.getInstance().navigation(DegradeService.class);if(null!=degradeService){degradeService.onLost(context,postcard);}}returnnull;}//执行成功回调if(null!=callback){callback.onFound(postcard);}//Provider和Fragment不走拦截器if(!postcard.isGreenChannel()){// It must be run in async thread, maybe interceptor cost too mush time made ANR.//执行拦截器的doInterceptions方法interceptorService.doInterceptions(postcard,newInterceptorCallback(){/** * Continue process * * @param postcard route meta */@OverridepublicvoidonContinue(Postcardpostcard){_navigation(postcard,requestCode,callback);}/** * Interrupt process, pipeline will be destory when this method called. * * @param exception Reson of interrupt. */@OverridepublicvoidonInterrupt(Throwableexception){if(null!=callback){callback.onInterrupt(postcard);}}});}else{return_navigation(postcard,requestCode,callback);}returnnull;}
ublicsynchronizedstaticvoidcompletion(Postcardpostcard){if(null==postcard){thrownewNoRouteFoundException(TAG+"No postcard!");}//获取RouteMetaRouteMetarouteMeta=Warehouse.routes.get(postcard.getPath());//首次调用routeMeta为nullif(null==routeMeta){// Maybe its does't exist, or didn't load.//如果map中不包含postcard的group则抛出异常if(!Warehouse.groupsIndex.containsKey(postcard.getGroup())){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.//将属于这个group中的所有路由都添加到map中addRouteGroupDynamic(postcard.getGroup(),null);//再次执行completion方法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()){//如果是Provider类型casePROVIDER:// if the route is provider, should find its instance// Its provider, so it must implement IProvider//创建Provider实例Class<?extendsIProvider>providerMeta=(Class<?extendsIProvider>)routeMeta.getDestination();//从缓存中获取ProviderIProviderinstance=Warehouse.providers.get(providerMeta);if(null==instance){// There's no instance of this providerIProviderprovider;try{//如果为空,创建IProviderprovider=providerMeta.getConstructor().newInstance();provider.init(mContext);Warehouse.providers.put(providerMeta,provider);instance=provider;}catch(Exceptione){thrownewHandlerException("Init provider failed! "+e.getMessage());}}postcard.setProvider(instance);//Provider和Fragment不走拦截器postcard.greenChannel();// Provider should skip all of interceptorsbreak;caseFRAGMENT:postcard.greenChannel();// Fragment needn't interceptorsdefault:break;}}}
privateObject_navigation(finalPostcardpostcard,finalintrequestCode,finalNavigationCallbackcallback){finalContextcurrentContext=postcard.getContext();switch(postcard.getType()){caseACTIVITY:// Build intent//创建IntentfinalIntentintent=newIntent(currentContext,postcard.getDestination());//设置参数intent.putExtras(postcard.getExtras());// Set flags.intflags=postcard.getFlags();if(0!=flags){intent.setFlags(flags);}// Non activity, need FLAG_ACTIVITY_NEW_TASKif(!(currentContextinstanceofActivity)){intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}// Set ActionsStringaction=postcard.getAction();if(!TextUtils.isEmpty(action)){intent.setAction(action);}// Navigation in main looper.runInMainThread(newRunnable(){@Overridepublicvoidrun(){startActivity(requestCode,currentContext,intent,postcard,callback);}});break;casePROVIDER:returnpostcard.getProvider();caseBOARDCAST:caseCONTENT_PROVIDER:caseFRAGMENT:Class<?>fragmentMeta=postcard.getDestination();try{Objectinstance=fragmentMeta.getConstructor().newInstance();if(instanceinstanceofFragment){((Fragment)instance).setArguments(postcard.getExtras());}elseif(instanceinstanceofandroid.support.v4.app.Fragment){((android.support.v4.app.Fragment)instance).setArguments(postcard.getExtras());}returninstance;}catch(Exceptionex){logger.error(Consts.TAG,"Fetch fragment instance error, "+TextUtils.formatStackTrace(ex.getStackTrace()));}caseMETHOD:caseSERVICE:default:returnnull;}returnnull;}
@OverridepublicvoiddoInterceptions(finalPostcardpostcard,finalInterceptorCallbackcallback){if(MapUtils.isNotEmpty(Warehouse.interceptorsIndex)){checkInterceptorsInitStatus();if(!interceptorHasInit){callback.onInterrupt(newHandlerException("Interceptors initialization takes too much time."));return;}//在子线程中执行LogisticsCenter.executor.execute(newRunnable(){@Overridepublicvoidrun(){CancelableCountDownLatchinterceptorCounter=newCancelableCountDownLatch(Warehouse.interceptors.size());try{_execute(0,interceptorCounter,postcard);interceptorCounter.await(postcard.getTimeout(),TimeUnit.SECONDS);if(interceptorCounter.getCount()>0){// Cancel the navigation this time, if it hasn't return anythings.callback.onInterrupt(newHandlerException("The interceptor processing timed out."));}elseif(null!=postcard.getTag()){// Maybe some exception in the tag.callback.onInterrupt((Throwable)postcard.getTag());}else{callback.onContinue(postcard);}}catch(Exceptione){callback.onInterrupt(e);}}});}else{callback.onContinue(postcard);}}
privatestaticvoid_execute(finalintindex,finalCancelableCountDownLatchcounter,finalPostcardpostcard){if(index<Warehouse.interceptors.size()){IInterceptoriInterceptor=Warehouse.interceptors.get(index);iInterceptor.process(postcard,newInterceptorCallback(){@OverridepublicvoidonContinue(Postcardpostcard){// Last interceptor excute over with no exception.counter.countDown();//一个接一个执行,如果中间有一个拦截器没有回调onContinue 后面的拦截器都将不执行_execute(index+1,counter,postcard);// When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.}@OverridepublicvoidonInterrupt(Throwableexception){// Last interceptor execute over with fatal exception.postcard.setTag(null==exception?newHandlerException("No message."):exception);// save the exception message for backup.counter.cancel();// Be attention, maybe the thread in callback has been changed,// then the catch block(L207) will be invalid.// The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!if(!Looper.getMainLooper().equals(Looper.myLooper())){// You shouldn't throw the exception if the thread is main thread.thrownewHandlerException(exception.getMessage());}}});}}