版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】ARouter的原理的使用
初始化ARouter在使用前需要通過調(diào)用Arouter.init方法并傳入Application進(jìn)行初始化:
/**
*Init,itmustbecallbeforeusedrouter.
*/
publicstaticvoidinit(Applicationapplication){
if(!hasInit){
logger=_ARouter.logger;
_AR(Consts.TAG,"ARouterinitstart.");
hasInit=_ARouter.init(application);
if(hasInit){
_ARouter.afterInit();
}
_AR(Consts.TAG,"ARouterinitover.");
}
}這里調(diào)用到了_ARouter.init,這個(gè)_ARouter類才是ARouter的核心類:
protectedstaticsynchronizedbooleaninit(Applicationapplication){
mContext=application;
LogisticsCenter.init(mContext,executor);
(Consts.TAG,"ARouterinitsuccess!");
hasInit=true;
//It'snotagoodidea.
//if(Build.VERSION.SDK_INT>Build.VERSION_CODES.ICE_CREAM_SANDWICH){
//
application.registerActivityLifecycleCallbacks(newAutowiredLifecycleCallback());
}
returntrue;
}這里實(shí)際上調(diào)用到了LogisticsCenter.init:publicsynchronizedstaticvoidinit(Contextcontext,ThreadPoolExecutortpe)throwsHandlerException{
mContext=context;
executor=tpe;
try{
longstartInit=System.currentTimeMillis();
Set<String>routerMap;
//獲取存儲(chǔ)ClassName集合的routerMap(debug模式下每次都會(huì)拿最新的)
if(ARouter.debuggable()||PackageUtils.isNewVersion(context)){
(TAG,"Runwithdebugmodeornewinstall,rebuildroutermap.");
//根據(jù)指定的packageName獲取package下的所有ClassName
routerMap=ClassUtils.getFileNameByPackageName(mContext,ROUTE_ROOT_PAKCAGE);
if(!routerMap.isEmpty()){
//存入SP緩存
context.getSharedPreferences(AROUTER_SP_CACHE_KEY,Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP,routerMap).apply();
}
}else{
(TAG,"Loadroutermapfromcache.");
//release模式下,已經(jīng)緩存了ClassName列表
routerMap=newHashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY,Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP,newHashSet<String>()));
}
(TAG,"Findroutermapfinished,mapsize="+routerMap.size()+",cost"+(System.currentTimeMillis()-startInit)+"ms.");
startInit=System.currentTimeMillis();
//遍歷ClassName
for(StringclassName:routerMap){
if(className.startsWith(ROUTE_ROOT_PAKCAGE+DOT+SDK_NAME+SEPARATOR+SUFFIX_ROOT)){
//發(fā)現(xiàn)是Root,加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)Warehouse.groupsIndex
((IRouteRoot)(Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
}elseif(className.startsWith(ROUTE_ROOT_PAKCAGE+DOT+SDK_NAME+SEPARATOR+SUFFIX_INTERCEPTORS)){
//發(fā)現(xiàn)是Interceptor,加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)WerceptorsIndex
((IInterceptorGroup)(Class.forName(className).getConstructor().newInstance())).loadInto(WerceptorsIndex);
}elseif(className.startsWith(ROUTE_ROOT_PAKCAGE+DOT+SDK_NAME+SEPARATOR+SUFFIX_PROVIDERS)){
//發(fā)現(xiàn)是ProviderGroup,加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)WvidersIndex
((IProviderGroup)(Class.forName(className).getConstructor().newInstance())).loadInto(WvidersIndex);
}
}
//...
}catch(Exceptione){
thrownewHandlerException(TAG+"ARouterinitlogisticscenterexception!["+e.getMessage()+"]");
}
}1.獲取com.alibaba.android.arouter.routes下存儲(chǔ)ClassName的集合routerMap。2.若為debug模式或之前沒有解析過routerMap,則通過ClassUtils.getFileNameByPackageName方法對(duì)指定package下的所有ClassName進(jìn)行解析并存入SP。3.若并非debug模式,并且之前已經(jīng)解析過,則直接從SP中取出。(debug每次都需要更新,因?yàn)轭悤?huì)隨著代碼的修改而變動(dòng))4.遍歷routerMap中的ClassName。如果是RouteRoot,則加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)Warehouse.groupsIndex。如果是InterceptorGroup,則加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)WerceptorsIndex。如果是ProviderGroup,則加載類構(gòu)建對(duì)象后通過loadInto加載進(jìn)WvidersIndex`。1.獲取com.alibaba.android.arouter.routes下存儲(chǔ)ClassName的集合routerMap。2.若為debug模式或之前沒有解析過routerMap,則通過ClassUtils.getFileNameByPackageName方法對(duì)指定package下的所有ClassName進(jìn)行解析并存入SP。3.若并非debug模式,并且之前已經(jīng)解析過,則直接從SP中取出。(debug每次都需要更新,因?yàn)轭悤?huì)隨著代碼的修改而變動(dòng))4.遍歷routerMap中的ClassName。我們先看看ClassUtils.getFileNameByPackageName是如何對(duì)指定package下的ClassName集合進(jìn)行解析的:
publicstaticSet<String>getFileNameByPackageName(Contextcontext,finalStringpackageName){
finalSet<String>classNames=newHashSet<>();
//通過getSourcePaths方法獲取dex文件path集合
List<String>paths=getSourcePaths(context);
//通過CountDownLatch對(duì)path的遍歷處理進(jìn)行控制
finalCountDownLatchparserCtl=newCountDownLatch(paths.size());
//遍歷path,通過DefaultPoolExecutor并發(fā)對(duì)path進(jìn)行處理
for(finalStringpath:paths){
DefaultPoolExecutor.getInstance().execute(newRunnable(){
@Override
publicvoidrun(){
//加載path對(duì)應(yīng)的dex文件
DexFiledexfile=null;
try{
if(path.endsWith(EXTRACTED_SUFFIX)){
//zip結(jié)尾通過DexFile.loadDex進(jìn)行加載
dexfile=DexFile.loadDex(path,path+".tmp",0);
}else{
//否則通過newDexFile加載
dexfile=newDexFile(path);
}
//遍歷dex中的Entry
Enumeration<String>dexEntries=dexfile.entries();
while(dexEntries.hasMoreElements()){
//如果是對(duì)應(yīng)的package下的類,則添加其className
StringclassName=dexEntries.nextElement();
if(className.startsWith(packageName)){
classNames.add(className);
}
}
}catch(Throwableignore){
Log.e("ARouter","Scanmapfileindexfilesmadeerror.",ignore);
}finally{
if(null!=dexfile){
try{
dexfile.close();
}catch(Throwableignore){
}
}
parserCtl.countDown();
}
}
});
}
//所有path處理完成后,繼續(xù)向下走
parserCtl.await();
Log.d(Consts.TAG,"Filter"+classNames.size()+"classesbypackageName<"+packageName+">");
returnclassNames;
}這里的步驟比較簡(jiǎn)單,主要是如下的步驟:1.通過getSourcePaths方法獲取dex文件的path集合。2.創(chuàng)建了一個(gè)CountDownLatch控制dex文件的并行處理,以加快速度。3.遍歷path列表,通過DefaultPoolExecutor對(duì)path并行處理。4.加載path對(duì)應(yīng)的dex文件,并對(duì)其中的Entry進(jìn)行遍歷,若發(fā)現(xiàn)了對(duì)應(yīng)package下的ClassName,將其加入結(jié)果集合。5.所有dex處理完成后,返回結(jié)果1.通過getSourcePaths方法獲取dex文件的path集合。2.創(chuàng)建了一個(gè)CountDownLatch控制dex文件的并行處理,以加快速度。3.遍歷path列表,通過DefaultPoolExecutor對(duì)path并行處理。4.加載path對(duì)應(yīng)的dex文件,并對(duì)其中的Entry進(jìn)行遍歷,若發(fā)現(xiàn)了對(duì)應(yīng)package下的ClassName,將其加入結(jié)果集合。5.所有dex處理完成后,返回結(jié)果關(guān)于getSourcePaths如何獲取到的dex集合這里就不糾結(jié)了,因?yàn)槲覀兊年P(guān)注點(diǎn)不在這里。Warehouse實(shí)際上就是倉庫的意思,它存放了ARouter自動(dòng)生成的類(RouteRoot、InterceptorGroup、ProviderGroup)的信息。我們先看看Warehouse類究竟是怎樣的:
classWarehouse{
//保存RouteGroup對(duì)應(yīng)的class以及RouteMeta
staticMap<String,Class<?extendsIRouteGroup>>groupsIndex=newHashMap<>();
staticMap<String,RouteMeta>routes=newHashMap<>();
//保存Provider以及RouteMeta
staticMap<Class,IProvider>providers=newHashMap<>();
staticMap<String,RouteMeta>providersIndex=newHashMap<>();
//保存Interceptor對(duì)應(yīng)的class以及Inteceptor
staticMap<Integer,Class<?extendsIInterceptor>>interceptorsIndex=newUniqueKeyTreeMap<>("Morethanoneinterceptorsusesamepriority[%s]");
staticList<IInterceptor>interceptors=newArrayList<>();
staticvoidclear(){
routes.clear();
groupsIndex.clear();
providers.clear();
providersIndex.clear();
interceptors.clear();
interceptorsIndex.clear();
}
}可以發(fā)現(xiàn)Warehouse就是一個(gè)純粹用來存放信息的倉庫類,它的數(shù)據(jù)的實(shí)際上是通過上面的幾個(gè)自動(dòng)生成的類在loadInto中對(duì)Warehouse主動(dòng)填入數(shù)據(jù)實(shí)現(xiàn)的。例如我們打開一個(gè)自動(dòng)生成的IRouteRoot的實(shí)現(xiàn)類:publicclassARouter$$Root$$homeworkimplementsIRouteRoot{
@Override
publicvoidloadInto(Map<String,Class<?extendsIRouteGroup>>routes){
routes.put("homework",ARouter$$Group$$homework.class);
}
}可以看到,它在groupsIndex中對(duì)這個(gè)RouteRoot中的IRouteGroup進(jìn)行了注冊(cè),也就是向groupIndex中注冊(cè)了RouteGroup對(duì)應(yīng)的IRouteGroup類。其他類也是一樣,通過自動(dòng)生成的代碼將數(shù)據(jù)填入Map或List中??梢园l(fā)現(xiàn),初始化過程主要完成了對(duì)自動(dòng)生成的路由相關(guān)類RouteRoot、Interceptor、ProviderGroup的加載,對(duì)它們通過反射構(gòu)造后將信息加載進(jìn)了Warehouse類中。下面我們看看路由的跳轉(zhuǎn)是如何實(shí)現(xiàn)的,我們先看到ARouter.build方法:publicPostcardbuild(Stringpath){
return_ARouter.getInstance().build(path);
}它轉(zhuǎn)調(diào)到了_ARouter的build方法:
protectedPostcardbuild(Stringpath){
if(TextUtils.isEmpty(path)){
thrownewHandlerException(Consts.TAG+"Parameterisinvalid!");
}else{
PathReplaceServicepService=ARouter.getInstance().navigation(PathReplaceService.class);
if(null!=pService){
path=pService.forString(path);
}
returnbuild(path,extractGroup(path));
}
}它首先通過ARouter.navigation獲取到了PathReplaceService,它需要用戶進(jìn)行實(shí)現(xiàn),若沒有實(shí)現(xiàn)會(huì)返回null,若有實(shí)現(xiàn)則調(diào)用了它的forString方法傳入了用戶的RoutePath進(jìn)行路徑的預(yù)處理。最后轉(zhuǎn)調(diào)到了build(path,group),group通過extractGroup得到:privateStringextractGroup(Stringpath){
if(TextUtils.isEmpty(path)||!path.startsWith("/")){
thrownewHandlerException(Consts.TAG+"Extractthedefaultgroupfailed,thepathmustbestartwith'/'andcontainmorethan2'/'!");
}
try{
StringdefaultGroup=path.substring(1,path.indexOf("/",1));
if(TextUtils.isEmpty(defaultGroup)){
thrownewHandlerException(Consts.TAG+"Extractthedefaultgroupfailed!There'snothingbetween2'/'!");
}else{
returndefaultGroup;
}
}catch(Exceptione){
logger.warning(Consts.TAG,"Failedtoextractdefaultgroup!"+e.getMessage());
returnnull;
}
}extractGroup實(shí)際上就是對(duì)字符串處理,取出RouteGroup的名稱部分。
protectedPostcardbuild(Stringpath,Stringgroup){
if(TextUtils.isEmpty(path)||TextUtils.isEmpty(group)){
thrownewHandlerException(Consts.TAG+"Parameterisinvalid!");
}else{
PathReplaceServicepService=ARouter.getInstance().navigation(PathReplaceService.class);
if(null!=pService){
path=pService.forString(path);
}
returnnewPostcard(path,group);
}
}build(path,group)方法同樣也會(huì)嘗試獲取到PathReplaceService并對(duì)path進(jìn)行預(yù)處理。之后通過path與group構(gòu)建了一個(gè)Postcard類:
publicPostcard(Stringpath,Stringgroup){
this(path,group,null,null);
}
publicPostcard(Stringpath,Stringgroup,Uriuri,Bundlebundle){
setPath(path);
setGroup(group);
setUri(uri);
this.mBundle=(null==bundle?newBundle():bundle);
}這里最終調(diào)用到了PostCard(path,group,uri,bundle),這里只是進(jìn)行了一些參數(shù)的設(shè)置。之后,如果我們調(diào)用withInt、withDouble等方法,就可以進(jìn)行參數(shù)的設(shè)置。例如withInt方法:
publicPostcardwithInt(@NullableStringkey,intvalue){
mBundle.putInt(key,value);
returnthis;
}它實(shí)際上就是在對(duì)Bundle中設(shè)置對(duì)應(yīng)的key、value。最后我們通過navigation即可實(shí)現(xiàn)最后的跳轉(zhuǎn):
publicObjectnavigation(){
returnnavigation(null);
}
publicObjectnavigation(Contextcontext){
returnnavigation(context,null);
}
publicObjectnavigation(Contextcontext,NavigationCallbackcallback){
returnARouter.getInstance().navigation(context,this,-1,callback);
}
publicvoidnavigation(ActivitymContext,intrequestCode){
navigation(mContext,requestCode,null);
}
publicvoidnavigation(ActivitymContext,intrequestCode,NavigationCallbackcallback){
ARouter.getInstance().navigation(mContext,this,requestCode,callback);
}通過如上的navigation可以看到,實(shí)際上它們都是最終調(diào)用到ARouter.navigation方法,在沒有傳入Context時(shí)會(huì)使用Application初始化的Context,并且可以通過NavigationCallback對(duì)navigation的過程進(jìn)行監(jiān)聽。
publicObjectnavigation(ContextmContext,Postcardpostcard,intrequestCode,NavigationCallbackcallback){
return_ARouter.getInstance().navigation(mContext,postcard,requestCode,callback);
}ARouter仍然只是將請(qǐng)求轉(zhuǎn)發(fā)到了_ARouter:
protectedObjectnavigation(finalContextcontext,finalPostcardpostcard,finalintrequestCode,finalNavigationCallbackcallback){
try{
//通過LogisticsCpletion對(duì)postcard進(jìn)行補(bǔ)全
LogisticsCpletion(postcard);
}catch(NoRouteFoundExceptionex){
//...
}
if(null!=callback){
callback.onFound(postcard);
}
//如果設(shè)置了greenChannel,會(huì)跳過所有攔截器的執(zhí)行
if(!postcard.isGreenChannel()){
//沒有跳過攔截器,對(duì)postcard的所有攔截器進(jìn)行執(zhí)行
interceptorService.doInterceptions(postcard,newInterceptorCallback(){
@Override
publicvoidonContinue(Postcardpostcard){
_navigation(context,postcard,requestCode,callback);
}
@Override
publicvoidonInterrupt(Throwableexception){
if(null!=callback){
callback.onInterrupt(postcard);
}
(Consts.TAG,"Navigationfailed,terminationbyinterceptor:"+exception.getMessage());
}
});
}else{
return_navigation(context,postcard,requestCode,callback);
}
returnnull;
}上面的代碼主要有以下步驟:1.通過LogisticsCpletion對(duì)postcard進(jìn)行補(bǔ)全。2.如果postcard沒有設(shè)置greenChannel,則對(duì)postcard的攔截器進(jìn)行執(zhí)行,執(zhí)行完成后調(diào)用_navigation方法真正實(shí)現(xiàn)跳轉(zhuǎn)。3.如果postcard設(shè)置了greenChannel,則直接跳過所有攔截器,調(diào)用_navigation方法真正實(shí)現(xiàn)跳轉(zhuǎn)。1.通過LogisticsCpletion對(duì)postcard進(jìn)行補(bǔ)全。2.如果postcard沒有設(shè)置greenChannel,則對(duì)postcard的攔截器進(jìn)行執(zhí)行,執(zhí)行完成后調(diào)用_navigation方法真正實(shí)現(xiàn)跳轉(zhuǎn)。3.如果postcard設(shè)置了greenChannel,則直接跳過所有攔截器,調(diào)用_navigation方法真正實(shí)現(xiàn)跳轉(zhuǎn)。我們看看LogisticsCpletion是如何實(shí)現(xiàn)postcard的補(bǔ)全的:
publicsynchronizedstaticvoidcompletion(Postcardpostcard){
if(null==postcard){
thrownewNoRouteFoundException(TAG+"Nopostcard!");
}
//通過Warehouse.routes.get嘗試獲取RouteMeta
RouteMetarouteMeta=Warehouse.routes.get(postcard.getPath());
if(null==routeMeta){
//若routeMeta為null,可能是并不存在,或是還沒有加載進(jìn)來
//嘗試獲取postcard的RouteGroup
Class<?extendsIRouteGroup>groupMeta=Warehouse.groupsIndex.get(postcard.getGroup());
//Loadroutemeta.
if(null==groupMeta){
thrownewNoRouteFoundException(TAG+"Thereisnoroutematchthepath["+postcard.getPath()+"],ingroup["+postcard.getGroup()+"]");
}else{
//...
//如果找到了對(duì)應(yīng)的RouteGroup,則將其加載進(jìn)來并重新調(diào)用completion進(jìn)行補(bǔ)全
IRouteGroupiGroupInstance=groupMeta.getConstructor().newInstance();
iGroupInstance.loadInto(Warehouse.routes);
Warehouse.groupsIndex.remove(postcard.getGroup());
//...
completion(postcard);
//Reload
}
}else{
//如果找到了對(duì)應(yīng)的routeMeta,將它的信息設(shè)置進(jìn)postcard中
postcard.setDestination(routeMeta.getDestination());
postcard.setType(routeMeta.getType());
postcard.setPriority(routeMeta.getPriority());
postcard.setExtra(routeMeta.getExtra());
UrirawUri=postcard.getUri();
//將uri中的參數(shù)設(shè)置進(jìn)bundle中
if(null!=rawUri){
Map<String,String>resultMap=TextUtils.splitQueryParameters(rawUri);
Map<String,Integer>paramsType=routeMeta.getParamsType();
if(MapUtils.isNotEmpty(paramsType)){
//Setvaluebyitstype,justforparamswhichannotationby@Param
for(Map.Entry<String,Integer>params:paramsType.entrySet()){
setValue(postcard,
params.getValue(),
params.getKey(),
resultMap.get(params.getKey()));
}
//Saveparamsnamewhichneedautoinject.
postcard.getExtras().putStringArray(ARouter.AUTO_INJECT,paramsType.keySet().toArray(newString[]{}));
}
//Saverawuri
postcard.withString(ARouter.RAW_URI,rawUri.toString());
}
//對(duì)于provider和fragment,進(jìn)行特殊處理
switch(routeMeta.getType()){
casePROVIDER:
//如果是一個(gè)provider,嘗試從Warehouse中查找它的類并構(gòu)造對(duì)象,然后將其設(shè)置到provider
Class<?extendsIProvider>providerMeta=(Class<?extendsIProvider>)routeMeta.getDestination();
IProviderinstance=Wviders.get(providerMeta);
if(null==instance){//There'snoinstanceofthisprovider
IProviderprovider;
try{
provider=providerMeta.getConstructor().newInstance();
provider.init(mContext);
Wviders.put(providerMeta,provider);
instance=provider;
}catch(Exceptione){
thrownewHandlerException("Initproviderfailed!"+e.getMessage());
}
}
postcard.setProvider(instance);
//provider和fragment都會(huì)跳過攔截器
postcard.greenChannel();
break;
caseFRAGMENT:
//provider和fragment都會(huì)跳過攔截器
postcard.greenChannel();
default:
break;
}
}
}這個(gè)方法主要完成了對(duì)postcard的信息與Warehouse的信息進(jìn)行結(jié)合,以補(bǔ)全postcard的信息,它的步驟如下:1.通過Warehouse.routes.get根據(jù)path嘗試獲取RouteMeta對(duì)象。2.若獲取不到RouteMeta對(duì)象,可能是不存在或是還沒有進(jìn)行加載(第一次都未加載),嘗試獲取RouteGroup調(diào)用其loadInto方法將RouteMeta加載進(jìn)Warehouse,最后調(diào)用completion重新嘗試補(bǔ)全。3.將RouteMeta的信息設(shè)置到postcard中,其中會(huì)將rawUri的參數(shù)設(shè)置進(jìn)Bundle。4.對(duì)于Provider和Fragment特殊處理,其中Provider會(huì)從Warehouse中加載并構(gòu)造它的對(duì)象,然后設(shè)置到postcard。Provider和Fragment都會(huì)跳過攔截器。1.通過Warehouse.routes.get根據(jù)path嘗試獲取RouteMeta對(duì)象。2.若獲取不到RouteMeta對(duì)象,可能是不存在或是還沒有進(jìn)行加載(第一次都未加載),嘗試獲取RouteGroup調(diào)用其loadInto方法將RouteMeta加載進(jìn)Warehouse,最后調(diào)用completion重新嘗試補(bǔ)全。3.將RouteMeta的信息設(shè)置到postcard中,其中會(huì)將rawUri的參數(shù)設(shè)置進(jìn)Bundle。4.對(duì)于Provider和Fragment特殊處理,其中Provider會(huì)從Warehouse中加載并構(gòu)造它的對(duì)象,然后設(shè)置到postcard。Provider和Fragment都會(huì)跳過攔截器。RouteGroup的loadInto仍然是自動(dòng)生成的,例如下面就是一些自動(dòng)生成的代碼:
publicvoidloadInto(Map<String,RouteMeta>atlas){
atlas.put("/homework/commit",RouteMeta.build(RouteType.ACTIVITY,HomeworkCommitActivity.class,"/homework/commit","homework",null,-1,-2147483648));
//...
}它包括了我們補(bǔ)全所需要的如Destination、Class、path等信息,在生成代碼時(shí)自動(dòng)根據(jù)注解進(jìn)行生成。我們看看navigation方法是如何實(shí)現(xiàn)的跳轉(zhuǎn):
privateObject_navigation(finalContextcontext,finalPostcardpostcard,finalintrequestCode,finalNavigationCallbackcallback){
finalContextcurrentContext=null==context?mContext:context;
switch(postcard.getType()){
caseACTIVITY:
//對(duì)Activity,構(gòu)造Intent,將參數(shù)設(shè)置進(jìn)去
finalIntentintent=newIntent(currentContext,postcard.getDestination());
intent.putExtras(postcard.getExtras());
//Setflags.
intflags=postcard.getFlags();
if(-1!=flags){
intent.setFlags(flags);
}elseif(!(currentContextinstanceofActivity)){
//Nonactivity,needlessoneflag.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
//切換到主線程,根據(jù)是否需要result調(diào)用不同的startActivity方法
newHandler(Looper.getMainLooper()).post(newRunnable(){
@Override
publicvoidrun(){
if(requestCode>0){
//Needstartforresult
ActivityCompat.startActivityForResult((Activity)currentContext,intent,requestCode,postcard.getOptionsBundle());
}else{
ActivityCompat.startActivity(currentContext,intent,postcard.getOptionsBundle());
}
if((0!=postcard.getEnterAnim()||0!=postcard.getExitAnim())&¤tContextinstanceofActivity){
//Oldversion.
((Activity)currentContext).overridePendingTransition(postcard.getEnterAnim(),postcard.getExitAnim());
}
if(null!=callback){//Navigationover.
callback.onArrival(postcard);
}
}
});
break;
casePROVIDER:
//provider直接返回對(duì)應(yīng)的provider
returnpostcard.getProvider();
caseBOARDCAST:
caseCONTENT_PROVIDER:
caseFRAGMENT:
//對(duì)于broadcast、contentprovider、fragment,構(gòu)造對(duì)象,設(shè)置參數(shù)后返回
ClassfragmentMeta=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,"Fetchfragmentinstanceerror,"+TextUtils.formatStackTrace(ex.getStackTrace()));
}
caseMETHOD:
caseSERVICE:
default:
returnnull;
}
returnnull;
}可以發(fā)現(xiàn),它會(huì)根據(jù)postcard的type來分別處理:可以發(fā)現(xiàn)ARouter的初始化和路由跳轉(zhuǎn)的整體邏輯還是不難的,實(shí)際上就是對(duì)Activity、Fragment的調(diào)轉(zhuǎn)過程進(jìn)行了包裝。ARouter除了可以通過ARouter.getInstance().build().navigation()這樣的方式實(shí)現(xiàn)頁面跳轉(zhuǎn)之外,還可以通過ARouter.getInstance().navigation(XXService.class)這樣的方式實(shí)現(xiàn)跨越組件的服務(wù)獲取,我們看看它是如何實(shí)現(xiàn)的:
public<T>Tnavigation(Class<?extendsT>service){
return_ARouter.getInstance().navigation(service);
}仍然跳轉(zhuǎn)到了_ARouter中去實(shí)現(xiàn):
protected<T>Tnavigation(Class<?extendsT>service){
try{
Postcardpostcard=LogisticsCenter.buildProvider(service.getName());
//Compatible1.0.5compilersdk.
//Earlierversionsdidnotusethefullyqualifiednametogettheservice
if(null==postcard){
//Noservice,orthisserviceinoldversion.
postcard=LogisticsCenter.buildProvider(service.getSimpleName());
}
if(null==postcard){
returnnull;
}
LogisticsCpletion(postcard);
return(T)postcard.getProvider();
}catch(NoRouteFoundExceptionex){
logger.warning(Consts.TAG,ex.getMessage());
returnnull;
}
}這里首先通過LogisticsCenter.buildProvider傳入service.class的name構(gòu)建出了一個(gè)postcard。而在ARouter老版本中,并不是通過這樣一個(gè)完整的name來獲取Service的,而是通過simpleName,下面為了兼容老版本,在獲取不到時(shí)會(huì)嘗試用老版本的方式重新構(gòu)建一次。之后會(huì)通過LogisticsCpletion對(duì)postcard進(jìn)行補(bǔ)全,最后通過postcard.Provider獲取對(duì)應(yīng)的Provider。除了buildProvider之外,其他方法我們已經(jīng)在前面進(jìn)行過分析,就不再贅述了:
publicstaticPostcardbuildProvider(StringserviceName){
RouteMetameta=WvidersIndex.get(serviceName);
if(null==meta){
returnnull;
}else{
returnnewPostcard(meta.getPath(),meta.getGroup());
}
}這里實(shí)際上非常簡(jiǎn)單,就是通過Warehouse中已經(jīng)初始化的providersIndex根據(jù)serviceName獲取對(duì)應(yīng)的RouteMeta,之后根據(jù)RouteMeta的path和group返回對(duì)應(yīng)的Postcard通過前面的分析,可以發(fā)現(xiàn)ARouter中存在一套攔截器機(jī)制,在completion的過程中對(duì)攔截器進(jìn)行了執(zhí)行,讓我們看看它的攔截器機(jī)制的實(shí)現(xiàn)。我們先看到IInterceptor接口:
publicinterfaceIInterceptorextendsIProvider{
/**
*Theoperationofthisinterceptor.
*
*@parampostcardmeta
*@paramcallbackcb
*/
voidprocess(Postcardpostcard,InterceptorCallbackcallback);
}攔截器中主要通過process方法完成執(zhí)行過程,可以在其中對(duì)postcard進(jìn)行處理。而攔截器的執(zhí)行我們知道,是通過InterceptorServiceImpl.doInterceptions實(shí)現(xiàn)的:
if(null!=Werceptors&&Werceptors.size()>0){
checkInterceptorsInitStatus();
if(!interceptorHasInit){
callback.onInterrupt(newHandlerException("Interceptorsinitializationtakestoomuchtime."));
return;
}
LogisticsCenter.executor.execute(newRunnable(){
@Override
publicvoidrun(){
CancelableCountDownLatchinterceptorCounter=newCancelableCountDownLatch(Werceptors.size());
try{
_excute(0,interceptorCounter,postcard);
interceptorCounter.await(postcard.getTimeout(),TimeUnit.SECONDS);
if(interceptorCounter.getCount()>0){
//Cancelthenavigationthistime,ifithasn'treturnanythings.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 施工項(xiàng)目部關(guān)鍵崗位人員任職條件及主要職責(zé)
- 地鐵站施工安全保證措施
- 安全施工會(huì)議紀(jì)要范文
- 橋梁施工安全技術(shù)交底范文
- 施工員年度工作總結(jié)及下年工作計(jì)劃
- 道路改造及綠化景觀工程施工進(jìn)度計(jì)劃及工期保證措施
- 涂料供貨合同
- 建設(shè)工程勘察設(shè)計(jì)合同文本
- 證券投資金托管協(xié)議書
- 團(tuán)隊(duì)凝聚力提升服務(wù)合同
- 手術(shù)室護(hù)理組長競(jìng)聘
- 電力系統(tǒng)繼電保護(hù)試題以及答案(二)
- 小學(xué)生防打架斗毆安全教育
- 2024-2025學(xué)年九年級(jí)英語上學(xué)期期末真題復(fù)習(xí) 專題09 單詞拼寫(安徽專用)
- 網(wǎng)絡(luò)運(yùn)營代銷合同范例
- 2024年新人教版七年級(jí)上冊(cè)歷史 第14課 絲綢之路的開通與經(jīng)營西域
- 《臨床放射生物學(xué)》課件
- 植保無人機(jī)安全飛行
- 2024年10月自考04532財(cái)務(wù)會(huì)計(jì)專題試題及答案含解析
- 醫(yī)療糾紛事件匯報(bào)
- 2024年村干部個(gè)人工作總結(jié)例文(3篇)
評(píng)論
0/150
提交評(píng)論