ARouter路由框架

Arouter框架适合项目比较大,模块多的时候,可以实现解耦,不需要知道跳转的是哪个activity,只需要知道配置参数就行 

1.ARouter通过解析URL实现路由跳转

2.支持多模块使用,容许分别打包

 3.Activity之间的跳转,普通的模式是

ARouter.getInstance().build("/test/MainActivity").withString("text","hello world") .navigation();

build里面是要跳转的目标,withString传递的是String类型的参数,navigation是跳转,一句代码完成跳转

4.在Application中进行初始化Arouter.init

public static void init(Application application) {

if(!hasInit) {

logger = _ARouter.logger;

_ARouter.logger.info("ARouter::","ARouter init start.");

hasInit = _ARouter.init(application);

if(hasInit) {

_ARouter.afterInit();

}

_ARouter.logger.info("ARouter::","ARouter init over.");

}

}

在 _ARouter.init(application)中调用了LogisticsCenter.init方法

在LogisticsCenter.init的方法中


public static synchronized void init(Context context, ThreadPoolExecutor tpe)throws HandlerException {

mContext = context;

executor = tpe;

try {

long e = System.currentTimeMillis();

Object routerMap;

if(!ARouter.debuggable() && !PackageUtils.isNewVersion(context)) {

ARouter.logger.info("ARouter::","Load router map from cache.");

routerMap =new HashSet(context.getSharedPreferences("SP_AROUTER_CACHE",0).getStringSet("ROUTER_MAP",new HashSet()));

}else {

ARouter.logger.info("ARouter::","Run with debug mode or new install, rebuild router map.");

routerMap = ClassUtils.getFileNameByPackageName(mContext,"com.alibaba.android.arouter.routes");

if(!((Set)routerMap).isEmpty()) {

context.getSharedPreferences("SP_AROUTER_CACHE",0).edit().putStringSet("ROUTER_MAP", (Set)routerMap).apply();

}

}

ARouter.logger.info("ARouter::","Find router map finished, map size = " + ((Set)routerMap).size() +", cost " + (System.currentTimeMillis() - e) +" ms.");

e = System.currentTimeMillis();

Iterator var5 = ((Set)routerMap).iterator();

while(var5.hasNext()) {

String className = (String)var5.next();

if(className.startsWith("com.alibaba.android.arouter.routes.ARouter$$Root")) {

((IRouteRoot)((IRouteRoot)Class.forName(className).getConstructor(new Class[0]).newInstance(new Object[0]))).loadInto(Warehouse.groupsIndex);

}else if(className.startsWith("com.alibaba.android.arouter.routes.ARouter$$Interceptors")) {

((IInterceptorGroup)((IInterceptorGroup)Class.forName(className).getConstructor(new Class[0]).newInstance(new Object[0]))).loadInto(Warehouse.interceptorsIndex);

}else if(className.startsWith("com.alibaba.android.arouter.routes.ARouter$$Providers")) {

((IProviderGroup)((IProviderGroup)Class.forName(className).getConstructor(new Class[0]).newInstance(new Object[0]))).loadInto(Warehouse.providersIndex);

}

}

ARouter.logger.info("ARouter::","Load root element finished, cost " + (System.currentTimeMillis() - e) +" ms.");

if(Warehouse.groupsIndex.size() ==0) {

ARouter.logger.error("ARouter::","No mapping files were found, check your configuration please!");

}

if(ARouter.debuggable()) {

ARouter.logger.debug("ARouter::", String.format(Locale.getDefault(),"LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]",new Object[]{Integer.valueOf(Warehouse.groupsIndex.size()), Integer.valueOf(Warehouse.interceptorsIndex.size()), Integer.valueOf(Warehouse.providersIndex.size())}));

}

}catch (Exception var7) {

throw new HandlerException("ARouter::ARouter init logistics center exception! [" + var7.getMessage() +"]");

}

}

通过 ClassUtils.getFileNameByPackageName这个类获得所有的这个包名的类,将获得包名的类保存的sp中

5.除了app编译产生的类之外,arouter—api也会产生三个类


找到所有的类型之后,三个分支创判断类名的开头

com.alibaba.android.arouter.routes.ARouter$$Root

com.alibaba.android.arouter.routes.ARouter$$Interceptors

com.alibaba.android.arouter.routes.ARouter$$Providers

已Root开头的类:

public class ARouter$$Root$$appimplements IRouteRoot {

@Override

  public void loadInto(Map> routes) {

routes.put("ui", ARouter$$Group$$ui.class);

}

}


public classARouter$$Root$$arouterapi implementsIRouteRoot{ @Override

  public void loadInto(Map>routes) {    routes.put("arouter", ARouter$$Group$$arouter.class);

  }

}

第一个在自己的模块中产生的类,后缀为app

第二个在arouter-api中产生的类,后缀为arouterapi 

(Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);

利用反射,调用loadInto方法,传递过去的参数是Warehouse.groupsIndex

传过去的是一个静态的HashMap , 也就是说将“组”的信息 , 以“组名” , “组类”以键值对的方式存入了 , Warehouse 的 groupsIndex 里面 , 从名字上看就是存储“组”的 .

在WareHouse中providersIndex,这里是以 名称RouteMeta为键值对存储 , RouteMeta保存着一些路由所需要的一些基本信息 ,

在ARouter.init中,调用调用了_ARouter.afterInit();进行了跳转

根据路径来进行跳转

public static synchronized void completion(Postcard postcard) {

if(null == postcard) {

throw new NoRouteFoundException("ARouter::No postcard!");

}else {

RouteMeta routeMeta = (RouteMeta)Warehouse.routes.get(postcard.getPath());

if(null == routeMeta) {

Class rawUri = (Class)Warehouse.groupsIndex.get(postcard.getGroup());

if(null == rawUri) {

throw new NoRouteFoundException("ARouter::There is no route match the path [" + postcard.getPath() +"], in group [" + postcard.getGroup() +"]");

}

try {

if(ARouter.debuggable()) {

ARouter.logger.debug("ARouter::", String.format(Locale.getDefault(),"The group [%s] starts loading, trigger by [%s]",new Object[]{postcard.getGroup(), postcard.getPath()}));

}

IRouteGroup providerMeta = (IRouteGroup)rawUri.getConstructor(new Class[0]).newInstance(new Object[0]);

providerMeta.loadInto(Warehouse.routes);

Warehouse.groupsIndex.remove(postcard.getGroup());

if(ARouter.debuggable()) {

ARouter.logger.debug("ARouter::", String.format(Locale.getDefault(),"The group [%s] has already been loaded, trigger by [%s]",new Object[]{postcard.getGroup(), postcard.getPath()}));

}

}catch (Exception var8) {

throw new HandlerException("ARouter::Fatal exception when loading group meta. [" + var8.getMessage() +"]");

}

completion(postcard);

}else {

postcard.setDestination(routeMeta.getDestination());

postcard.setType(routeMeta.getType());

postcard.setPriority(routeMeta.getPriority());

postcard.setExtra(routeMeta.getExtra());

Uri rawUri1 = postcard.getUri();

if(null != rawUri1) {

Map providerMeta1 = TextUtils.splitQueryParameters(rawUri1);

Map instance = routeMeta.getParamsType();

if(MapUtils.isNotEmpty(instance)) {

Iterator provider = instance.entrySet().iterator();

while(provider.hasNext()) {

Entry e = (Entry)provider.next();

setValue(postcard, (Integer)e.getValue(), (String)e.getKey(), (String)providerMeta1.get(e.getKey()));

}

postcard.getExtras().putStringArray("wmHzgD4lOj5o4241", (String[])instance.keySet().toArray(new String[0]));

}

postcard.withString("NTeRQWvye18AkPd6G", rawUri1.toString());

}

switch(null.$SwitchMap$com$alibaba$android$arouter$facade$enums$RouteType[routeMeta.getType().ordinal()]) {

case 1:

Class providerMeta2 = routeMeta.getDestination();

IProvider instance1 = (IProvider)Warehouse.providers.get(providerMeta2);

if(null == instance1) {

try {

IProvider provider1 = (IProvider)providerMeta2.getConstructor(new Class[0]).newInstance(new Object[0]);

provider1.init(mContext);

Warehouse.providers.put(providerMeta2, provider1);

instance1 = provider1;

}catch (Exception var7) {

throw new HandlerException("Init provider failed! " + var7.getMessage());

}

}

postcard.setProvider(instance1);

postcard.greenChannel();

break;

case 2:

postcard.greenChannel();

}

}

}

}

1. build()返回一个PostCard对象 , 包含路径 , 组名

2,调用PostCard的navigation()方法 , navigation()方法中调用LogisticsCenter.completion()方法并把包含路径 , 组名的postCard传过去 . 

3.在warehouse中进行搜索,首先会从routes中寻找着信息,如果没有,去groupIndex中寻找,找到了相应的信息,添加到routes缓存中,并存groupIndex中去掉

4.找到相应的类之后,再去postCard,再去设置类,类型优先级,传递过去的额外数据

5.接着根据postCard类型判断,如果是fragment或者是provider,就就去绿色通道,如果没有手动设置,会被arouter-api中的全局拦截器被拦截掉


在跳转中

private Object _navigation(Context context,final Postcard postcard,final int requestCode,final NavigationCallback callback) {

final Context currentContext =null == context?mContext:context;

switch(null.$SwitchMap$com$alibaba$android$arouter$facade$enums$RouteType[postcard.getType().ordinal()]) {

case 1:

final Intent intent =new Intent(currentContext, postcard.getDestination());

intent.putExtras(postcard.getExtras());

int flags = postcard.getFlags();

if(-1 != flags) {

intent.setFlags(flags);

}else if(!(currentContextinstanceof Activity)) {

intent.setFlags(268435456);

}

(new Handler(Looper.getMainLooper())).post(new Runnable() {

public void run() {

if(requestCode >0) {

ActivityCompat.startActivityForResult((Activity)currentContext, intent, requestCode, postcard.getOptionsBundle());

}else {

ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());

}

if((0 != postcard.getEnterAnim() ||0 != postcard.getExitAnim()) && currentContextinstanceof Activity) {

((Activity)currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());

}

if(null != callback) {

callback.onArrival(postcard);

}

}

});

return null;

case 2:

return postcard.getProvider();

case 3:

case 4:

case 5:

Class fragmentMeta = postcard.getDestination();

try {

Object ex = fragmentMeta.getConstructor(new Class[0]).newInstance(new Object[0]);

if(exinstanceof Fragment) {

((Fragment)ex).setArguments(postcard.getExtras());

}else if(exinstanceof android.support.v4.app.Fragment) {

((android.support.v4.app.Fragment)ex).setArguments(postcard.getExtras());

}

return ex;

}catch (Exception var10) {

logger.error("ARouter::","Fetch fragment instance error, " + TextUtils.formatStackTrace(var10.getStackTrace()));

}

case 6:

case 7:

default:

return null;

}

}

根据type来执行操作

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • ARouter探究(一) 前言 ARouter 是 Alibaba 开源的一款 Android 页面路由框架,特别...
    Jason骑蜗牛看世界阅读 1,313评论 1 3
  • ARouter源码解读 以前看优秀的开源项目,看到了页面路由框架ARouter,心想页面路由是个啥东东,于是乎网上...
    陆元伟阅读 499评论 0 1
  • 一、ARouter介绍及主要应用场景: 1、介绍: 是ARouter是阿里巴巴开源的Android平台中对页面、服...
    OneXzgj阅读 5,442评论 3 34
  • 开发一款App,总会遇到各种各样的需求和业务,这时候选择一个简单好用的轮子,就可以事半功倍 前言 上面一段代码,在...
    WangDeFa阅读 65,644评论 44 199
  • 前一秒你以为自己是天才,后一秒就怀疑自己根本不是这块料;能不能发挥好这个问题,就是薛定谔的猫,不到真实演出你根本不知道。
    爱你的Lisa阅读 89评论 0 0