Android开发

ARouter路由框架

2018-04-27  本文已影响0人  破晓11

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来执行操作

上一篇 下一篇

猜你喜欢

热点阅读