ARouter源码再分析
一、概述
ARouter是一个路由框架,主要解决平行模块之间页面跳转的问题。
ARouter基本原理---->ps:简化版:
1.其核心还是通过Intent进行跳转
2.通过注解+APT+JavaPoet技术,把项目中包含有@Router(path)注解的类找出来,然后把含有注解@Rotue的类和路由路径path一一映射。然后保存在Map中。
3.通过ARouter.getInstance().build(path).navigation()做页面跳转,根据路由path找到对应的Activity,并通过intent进行跳转
ps:下面就来看看简化版的源码分析
二、源码分析
源码分析主要看以下几个方法:
1.ARouter.init(applicationContex)//初始化
2.ARouter.getInstance.build(路由path).navigation()//跳转
一、初始化init方法的调用关系
ARouter的init方法啥也没做,只是调用了_ARouter.init()方法,而_ARouter.init方法中又调用了LogisticsCenter.init方法,然后使用其init方法把包含@Router的类映射到Warsehouse中。其主要的代码就在这里
ARouter.init()方法
public static void init(Application application) { if (!hasInit) { ......省略
//等于说啥也没做,就是包装了一下 hasInit = _ARouter.init(application); ....省略 } }
_ARouter.init方法
protected static synchronized boolean init(Application application) { mContext = application; LogisticsCenter.init(mContext, executor);//交给LogisticsCenter去初始化 logger.info(Consts.TAG, "ARouter init success!"); hasInit = true; mHandler = new Handler(Looper.getMainLooper());//创建了一个MainHandler return true; }
LogisticsCenter.init方法 public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException { mContext = context; executor = tpe; try { .... loadRouterMap(); if (registerByPlugin) {//检查插件 logger.info(TAG, "Load router map by arouter-auto-register plugin."); } else { Set<String> routerMap; // 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 generated by arouter-compiler. routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);//从包中加载类路径存入集合,包中的类是通过APT+JavaPoet提前生成的 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 finishes. } else { logger.info(TAG, "Load router map from cache.");
//在缓存中加载含有@Router注解的类路径 routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>())); } ........ for (String className : routerMap) { if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) { // This one of root elements, load root.实例化@Router标注的类后一个个的加入到Warehouse.groupsIndex(ps:其是一个map,在执行navigation的时候会用到这个东西) ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex); } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) { ....... } } } ....... }
二、执行build.(path).navigation()跳转
1.build(path)方法最主要的的目的是生成一个Postcard对象,并把path复制给Postcard对象。而这个对象的主要作用就是存储跳转信息。
protected Postcard build(String path, String group, Boolean afterReplace) { if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) { throw new HandlerException(Consts.TAG + "Parameter is invalid!"); } else { if (!afterReplace) { PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class); if (null != pService) { path = pService.forString(path); } } return new Postcard(path, group);//最终的目的,就是为了生成Postcard对象, } }
2.navigation()方法最主要的作用就是利用Postcard对象中的信息做跳转
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class); ....省略 LogisticsCenter.completion(postcard); ....省略 ....省略return _navigation(context, postcard, requestCode, callback); ....省略 return null; }
以上就是_ARouter中的navigation方法,里面有来个重要的方法,分别是:LogisticsCenter.completion(postcard)、_navigation()
LogisticsCenter.completion()方法主要是用来获取路由信息,并把路由信息存入postcard中。
public synchronized static void completion(Postcard postcard) { ... RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());//根据路由路径获取路由对象 .....
//设置路由参数
postcard.setDestination(routeMeta.getDestination()); postcard.setType(routeMeta.getType()); postcard.setPriority(routeMeta.getPriority()); postcard.setExtra(routeMeta.getExtra()); ...... }
_navigation()方法中实现真正的跳转
private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) { final Context currentContext = null == context ? mContext : context; switch (postcard.getType()) {//跳转类型,四大组件外加一个Fragment case ACTIVITY: // Build intent final Intent intent = new Intent(currentContext, postcard.getDestination());//从postcard中获取跳转信息 intent.putExtras(postcard.getExtras());//设置跳转参数 // Set flags. int flags = postcard.getFlags(); if (-1 != flags) { intent.setFlags(flags); } else if (!(currentContext instanceof Activity)) { // Non activity, need less one flag. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//启动一个新的activity } ...... // Navigation in main looper. runInMainThread(new Runnable() { @Override public void run() { startActivity(requestCode, currentContext, intent, postcard, callback);//在主线程中执行跳转动作 } }); ......return null; }
到此分析算是完,大概得意思就是ARouter是一个路由框架。原理是:通过APT找到@Router(path)注解标注的类,并于注解上的path做映射.存入HashMap中并加载到内存。ARouter通过build(path).navigation()跳转的时候通过path从HashMap中取出路由信息,封装Intent后进行跳转。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2013-08-22 Android调用系统的发邮件功能
2013-08-22 Android向手机通讯录中的所有的联系人(包括SIM卡),向手机通讯录中插入联系人