02.实现组件跳转方式php
04.跨进程组件通讯java
06.ARouter的工做流程android
07.ARouter简单调用apigit
以下所示github
优点有:web
劣势有:面试
优点有:segmentfault
劣势有:api
跨组件间通讯实现的同时,应该知足如下条件:缓存
ARouter主要由三部分组成,包括对外提供的api调用模块、注解模块以及编译时经过注解生产相关的类模块。
annotation模块
compiler模块
api模块
初始化代码以下所示
/**
*/ public static void init(Application application) { //若是没有初始化,则 if (!hasInit) { logger = _ARouter.logger; _ARouter.logger.info(Consts.TAG, "ARouter init start."); //作初始化工做 hasInit = _ARouter.init(application); if (hasInit) { _ARouter.afterInit(); } _ARouter.logger.info(Consts.TAG, "ARouter init over."); } } ```
以后接着看_ARouter.init(application)这行代码,点击去查看
protected static synchronized boolean init(Application application) { //赋值上下文 mContext = application; //初始化LogisticsCenter LogisticsCenter.init(mContext, executor); logger.info(Consts.TAG, "ARouter init success!"); hasInit = true; mHandler = new Handler(Looper.getMainLooper()); return true; }
接下来看看LogisticsCenter里面作了什么
public class LogisticsCenter { /**
*/ public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException { mContext = context; executor = tpe; try { long startInit = System.currentTimeMillis(); Set<String> routerMap; //debug或者版本更新的时候每次都从新加载router信息 // It will rebuild router map every times when debuggable. if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) { logger.info(TAG, "Run with debug mode or new install, rebuild router map."); // These class was generate by arouter-compiler. //加载alibaba.android.arouter.routes包下载的类 routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE); if (!routerMap.isEmpty()) { context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply(); } PackageUtils.updateVersion(context); // Save new version name when router map update finish. } else { logger.info(TAG, "Load router map from cache."); routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>())); } logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms."); startInit = System.currentTimeMillis(); for (String className : routerMap) { if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { // This one of root elements, load root. //导入ARouter$$Root$$app.java,初始化Warehouse.groupsIndex集合 ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { // Load interceptorMeta //导入ARouter$$Interceptors$$app.java,初始化Warehouse.interceptorsIndex集合 ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) { // Load providerIndex //导入ARouter$$Providers$$app.java,初始化Warehouse.providersIndex集合 ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex); } } /*******部分代码省略********/ } catch (Exception e) { throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]"); } } } ```
综上所述,整个初始化的流程大概就是:
最简单的调用方式
ARouter.getInstance() .build("/user/UserFragment") .navigation();
这个主要是添加跳转的路径
public Postcard build(String path) { return _ARouter.getInstance().build(path); }
而后把这个路径添加到默认的组中
/**
*/ 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)); } } ```
以下所示
final class _ARouter { protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { try { LogisticsCenter.completion(postcard); } catch (NoRouteFoundException ex) { /**************部分代码省略***************/ if (null != callback) { callback.onLost(postcard); } else { // No callback for this invoke, then we use the global degrade service. DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class); if (null != degradeService) { degradeService.onLost(context, postcard); } } 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(context, postcard, requestCode, callback); } @Override public void onInterrupt(Throwable exception) { //中断处理 if (null != callback) { callback.onInterrupt(postcard); } } }); } else { return _navigation(context, postcard, requestCode, callback); } return null; } private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { //没有上下文环境,就用Application的上下文环境 final Context currentContext = null == context ? mContext : context; switch (postcard.getType()) { case ACTIVITY: // Build intent 构建跳转的intent final Intent intent = new Intent(currentContext, postcard.getDestination()); intent.putExtras(postcard.getExtras()); // Set flags. 设置flag int flags = postcard.getFlags(); if (-1 != flags) { intent.setFlags(flags); } else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag. //若是上下文不是Activity,则添加FLAG_ACTIVITY_NEW_TASK的flag intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } // Navigation in main looper. 切换到主线程中 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (requestCode > 0) { // Need start for result ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle()); } else { ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle()); } if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) { // Old version. ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim()); } if (null != callback) { // Navigation over. callback.onArrival(postcard); } } }); 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; } }
看看代码以下所示
//Postcard继承于RouteMeta public final class Postcard extends RouteMeta //而后看看编译生成的文件 /**
public class ARouter$$Group$$me implements IRouteGroup { @Override public void loadInto(Map<String, RouteMeta> atlas) { atlas.put("/me/ExperienceCouponActivity", RouteMeta.build(RouteType.ACTIVITY, ExperienceCouponActivity.class, "/me/experiencecouponactivity", "me", null, -1, -2147483648)); atlas.put("/me/ServiceActivity", RouteMeta.build(RouteType.ACTIVITY, ServiceActivity.class, "/me/serviceactivity", "me", null, -1, -2147483648)); atlas.put("/me/SettingActivity", RouteMeta.build(RouteType.ACTIVITY, SettingActivity.class, "/me/settingactivity", "me", null, -1, -2147483648)); atlas.put("/me/UdeskServiceActivity", RouteMeta.build(RouteType.ACTIVITY, UdeskServiceActivity.class, "/me/udeskserviceactivity", "me", null, -1, -2147483648)); } } ```
首先,自定义一个类,须要继承DegradeService类,以下所示
/** * <pre> * @author 杨充 * blog : https://github.com/yangchong211 * time : 2018/08/24 * desc : ARouter路由降级处理 * revise:
*/ @Route(path = DegradeServiceImpl.PATH) public class DegradeServiceImpl implements DegradeService { static final String PATH = "/service/DegradeServiceImpl"; @Override public void onLost(Context context, Postcard postcard) { if (context != null && postcard.getGroup().equals("activity")) { Intent intent = new Intent(context, WebViewActivity.class); intent.putExtra(Constant.URL, Constant.GITHUB); intent.putExtra(Constant.TITLE, "github地址"); ActivityCompat.startActivity(context, intent, null); } } @Override public void init(Context context) { } } ```
如何使用该降级方案,十分简单。
NavigationCallback callback = new NavCallback() { @Override public void onArrival(Postcard postcard) { LogUtils.i("ARouterUtils"+"---跳转完了"); } @Override public void onFound(Postcard postcard) { super.onFound(postcard); LogUtils.i("ARouterUtils"+"---找到了"); } @Override public void onInterrupt(Postcard postcard) { super.onInterrupt(postcard); LogUtils.i("ARouterUtils"+"---被拦截了"); } @Override public void onLost(Postcard postcard) { super.onLost(postcard); LogUtils.i("ARouterUtils"+"---找不到了"); DegradeServiceImpl degradeService = new DegradeServiceImpl(); degradeService.onLost(Utils.getApp(),postcard); } };
在ARouter模块的时候讲述Interceptor的使用,若是本次路由跳转不是走的绿色通道那么则会触发拦截器进行过滤。
final class _ARouter { protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { /************部分代码省略************/ if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR. interceptorService.doInterceptions(postcard, new InterceptorCallback() { /**
* * @param postcard route meta */ @Override public void onContinue(Postcard postcard) { _navigation(context, postcard, requestCode, callback); } /** * Interrupt process, pipeline will be destory when this method called. * * @param exception Reson of interrupt. */ @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(context, postcard, requestCode, callback); } return null; } } ```
拦截器的初始化
final class _ARouter { static void afterInit() { // Trigger interceptor init, use byName. interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation(); } }
InterceptorServiceImpl的init方法:
@Route(path = "/arouter/service/interceptor") public class InterceptorServiceImpl implements InterceptorService { @Override public void init(final Context context) { LogisticsCenter.executor.execute(new Runnable() { @Override public void run() { if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) { //循环遍历仓库中的拦截器 for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) { Class<? extends IInterceptor> interceptorClass = entry.getValue(); try { //反射机制构造自定义的每个拦截器实例 IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance(); iInterceptor.init(context); //并将其添加在缓存中 Warehouse.interceptors.add(iInterceptor); } catch (Exception ex) { throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]"); } } interceptorHasInit = true; logger.info(TAG, "ARouter interceptors init over."); synchronized (interceptorInitLock) { interceptorInitLock.notifyAll(); } } } }); } }
拦截器的工做过程
@Route(path = "/arouter/service/interceptor") public class InterceptorServiceImpl implements InterceptorService { @Override public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) { if (null != Warehouse.interceptors && Warehouse.interceptors.size() > 0) { //检测是否初始化完全部的烂机器 checkInterceptorsInitStatus(); //没有完成正常的初始化,抛异常 if (!interceptorHasInit) { callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time.")); return; } //顺序遍历每个拦截器, LogisticsCenter.executor.execute(new Runnable() { @Override public void run() { CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size()); try { _excute(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(new HandlerException("The interceptor processing timed out.")); } else if (null != postcard.getTag()) { // Maybe some exception in the tag. callback.onInterrupt(new HandlerException(postcard.getTag().toString())); } else { callback.onContinue(postcard); } } catch (Exception e) { callback.onInterrupt(e); } } }); } else { callback.onContinue(postcard); } } //执行拦截器的过滤事件 private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) { if (index < Warehouse.interceptors.size()) { IInterceptor iInterceptor = Warehouse.interceptors.get(index); iInterceptor.process(postcard, new InterceptorCallback() { @Override public void onContinue(Postcard postcard) { // Last interceptor excute over with no exception. counter.countDown(); //若是当前没有拦截过滤,那么使用下一个拦截器 _excute(index + 1, counter, postcard); // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know. } @Override public void onInterrupt(Throwable exception) { // Last interceptor excute over with fatal exception. postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); // save the exception message for backup. counter.cancel(); } }); } } }
可查看multidex源码:
public class ClassUtils { /** * Identifies if the current VM has a native support for multidex, meaning there is no need for
* * @return true if the VM handles multidex */ private static boolean isVMMultidexCapable() { boolean isMultidexCapable = false; String vmName = null; try { if (isYunOS()) { // YunOS须要特殊判断 vmName = "'YunOS'"; isMultidexCapable = Integer.valueOf(System.getProperty("ro.build.version.sdk")) >= 21; } else { // 非YunOS原生Android vmName = "'Android'"; String versionString = System.getProperty("java.vm.version"); if (versionString != null) { Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString); if (matcher.matches()) { try { int major = Integer.parseInt(matcher.group(1)); int minor = Integer.parseInt(matcher.group(2)); isMultidexCapable = (major > VM_WITH_MULTIDEX_VERSION_MAJOR) || ((major == VM_WITH_MULTIDEX_VERSION_MAJOR) && (minor >= VM_WITH_MULTIDEX_VERSION_MINOR)); } catch (NumberFormatException ignore) { // let isMultidexCapable be false } } } } } catch (Exception ignore) { } Log.i(Consts.TAG, "VM with name " + vmName + (isMultidexCapable ? " has multidex support" : " does not have multidex support")); return isMultidexCapable; } } ```
什么是InstantRun支持?
以下所示