珠海网站建设乐云seo在线制作广告联盟代理平台
- 作者: 五速梦信息网
- 时间: 2026年03月21日 05:04
当前位置: 首页 > news >正文
珠海网站建设乐云seo在线制作,广告联盟代理平台,安阳企业网站建设,网站建设公司怎么盈利一、简介
众所周知#xff0c;在日常开发中#xff0c;随着项目业务越来越复杂#xff0c;项目中的代码量也越来越多#xff0c;如果维护、扩展、解耦等成了一个非常头疼问题#xff0c;随之孕育而生的诸如插件化、组件化、模块化等热门技术。 而其中组件化中一项的难点在日常开发中随着项目业务越来越复杂项目中的代码量也越来越多如果维护、扩展、解耦等成了一个非常头疼问题随之孕育而生的诸如插件化、组件化、模块化等热门技术。 而其中组件化中一项的难点就是实现各个组件之间的通讯我们通常解决方案采用路由中间件来实现页面之间跳转关系。 ARouter 是阿里开源路由框架常被用于组件之间、模块之间的跳转由于是国人团队开发的所以你懂的中文文档非常详细。
二、入门
2.1.添加依赖
android {defaultConfig {…javaCompileOptions {annotationProcessorOptions {arguments [AROUTER_MODULE_NAME: project.getName()]}}}
}dependencies {apicom.alibaba:arouter-api:1.5.0annotationProcessor com.alibaba:arouter-compiler:1.2.2
}2.2.初始化
在 Application 中初始化
if (BuildConfig.DEBUG) {ARouter.openLog() // 打印日志ARouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行必须开启调试模式线上版本需要关闭,否则有安全风险)
}
ARouter.init(this);2.3.添加注解
Route(path /main/main_main)
public class MainActivity extend BaseActivity {…
}2.4.发起路由
// 1.应用内简单的跳转(通过URL跳转在进阶用法中)
ARouter.getInstance().build(/main/main_main).navigation();// 2.跳转并携带参数
ARouter.getInstance().build(/main/main_main).withLong(id, 10086L).withString(name, Test).navigation();三、原理解析
在原理解析之前我们先了解 ARouter 使用关键技术-APTAnnotation Processing Tool它是 javac 的一个工具中文译名为编译时注解处理器说白了APT 用来编译时扫描和处理注解获取注解和被注解类等相关信息拿到这些信息之后自动生成一些代码核心是 AbstractProcessor 这个类APT 运用非常广泛诸如 ButterKnife、EventBus、Dagger2 等使用运用到了 APTARouter 也不例外。运用 APT 技术我们可以自己写一些注解处理器例如处理网络、打印出错信息等。
3.1 分析
我们来看看 ARouter 初始化
//1.初始化
ARouter.init(application)//2.ARouter#init
public static void init(Application application) {if (!hasInit) {logger _ARouter.logger;_ARouter.logger.info(Consts.TAG, ARouter init start.);//委托给_ARouter去初始化hasInit _ARouter.init(application);if (hasInit) {_ARouter.afterInit();}//初始化之后调用afterInit_ARouter.logger.info(Consts.TAG, ARouter init over.);}}从上面我们可以看到 ARouter 采用门面模式实际上委托给 *ARouter 处理*ARouter 是整个框架的路由中心控制器负责处理控制整个路由的流程。接下来我们看看 _ARouter 初始化化。
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#init
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {mContext context;executor tpe;try {long startInit System.currentTimeMillis();loadRouterMap();if (registerByPlugin) {logger.info(TAG, Load router map by arouter-auto-register plugin.);} else {SetString routerMap;//1.如果是debug模式或者有更新if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {logger.info(TAG, Run with debug mode or new install, rebuild router map.);//1.扫描包获取ROUTE_ROOT_PAKCAGEcom.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 finishes.} else {logger.info(TAG, Load router map from cache.);//2.获取本地缓存routerMap new HashSet(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSetString()));}logger.info(TAG, Find router map finished, map size routerMap.size() , cost (System.currentTimeMillis() - startInit) ms.);startInit System.currentTimeMillis();for (String className : routerMap) {//3.将 IRouteRootIRouteGroup和IProviderGroup的实现类//通过注解生成并且加载 Warehouse(数据仓库)// Warehouse:数据仓库存储路由配置信息和具体生成的IProvider对象if (className.startsWith(ROUTE_ROOT_PAKCAGE DOT SDK_NAME SEPARATOR SUFFIX_ROOT)) {//1.加载 IRouteRoot每个moudle下都会生成一个该类型的实现类//通过module名来区分的作用是将每个module下所有的分组按照组名//和对应分组的实现类(IRouteGroup接口的实现类)的 Class 对象做一个映射//然后保存在一个全局的 groupIndex 的 map 表中。((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);} else if (className.startsWith(ROUTE_ROOT_PAKCAGE DOT SDK_NAME SEPARATOR SUFFIX_INTERCEPTORS)) {//2.加载 IInterceptorGroup 作用是将各个module下的 自定义的i nterceptor 按照优先级和 interceptor的 // Class 对象做一个映射然后保存在一个全局的 interceptorIndex 的 map 表中。((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);} else if (className.startsWith(ROUTE_ROOT_PAKCAGE DOT SDK_NAME SEPARATOR SUFFIX_PROVIDERS)) {//3.加载 IProviderGroup 该类的作用的是将项目中自定义的提供序//列化功能的类的相关信息以RouteMeta 类的对象保存在全局的providerIndex的map表中((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);}}}logger.info(TAG, Load root element finished, cost (System.currentTimeMillis() - startInit) ms.);if (Warehouse.groupsIndex.size() 0) {logger.error(TAG, No mapping files were found, check your configuration please!);}if (ARouter.debuggable()) {logger.debug(TAG, String.format(Locale.getDefault(), LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d], Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));}} catch (Exception e) {throw new HandlerException(TAG ARouter init logistics center exception! [ e.getMessage() ]);}}从上面代码我们可以看到调用 LogisticsCenter后勤中心主要完成两件事 获取到 com.alibaba.android.arouter.routes 包下的所有 class 文件类名 根据找到的类名去加载相关的实例到Warehouse中com.alibaba.android.arouter.routes 包下面的 class 是注解解析器自动生成主要 IRouteRootIRouteGroup 和 IProviderGroup 的实现类当我们使用 Route 注解某个类时会将这个类的信息注入的到自动生成的上述实现类中。 接下来调用 afterInit()。
//_ARouter#afterInit
static void afterInit() {// 调用 Postcard#build 方法获取 InterceptorService 拦截服务控制器interceptorService (InterceptorService) ARouter.getInstance().build(/arouter/service/interceptor).navigation();}//build 方法实际上将 path 和 group 信息封装到 Postcard生成一个要跳转的信息表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));}}//Postcard#navigation 这个方法实现了跳转我们点进去会发现最后调用 _ARouter#navigation
//_ARouter#navigation
protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {PretreatmentService pretreatmentService ARouter.getInstance().navigation(PretreatmentService.class);if (null ! pretreatmentService !pretreatmentService.onPretreatment(context, postcard)) {// Pretreatment failed, navigation canceled.return null;}try {//1.调用 LogisticsCenter#completion 的方法LogisticsCenter.completion(postcard);……//不是绿色通道通过拦截控制器依次调用不同拦截器处理信息 if (!postcard.isGreenChannel()) { //每个拦截器的拦截方法调用都是在子线程中执行的interceptorService.doInterceptions(postcard, new InterceptorCallback() {Overridepublic void onContinue(Postcard postcard) {_navigation(context, postcard, requestCode, callback);}Overridepublic void onInterrupt(Throwable exception) {if (null ! callback) {//只要有一个拦截器拦截该包裹则回调onInterrupt方法宣告本次路由被终止callback.onInterrupt(postcard);}}});} else {//2.如果是绿色通道调用_navigation方法进行具体的导航return _navigation(context, postcard, requestCode, callback);}return null;} }//LogisticsCenter#completion
public synchronized static void completion(Postcard postcard) {……//1.Warehouse.routes获取RouteMetaRouteMeta 路由信息描述类存储目标地址的类型路径参数等信RouteMeta routeMeta Warehouse.routes.get(postcard.getPath());if (null routeMeta) { //如果没有路由信息则尝试去数据仓库查找Class? extends IRouteGroup groupMeta Warehouse.groupsIndex.get(postcard.getGroup()); if (null groupMeta) {throw new NoRouteFoundException(TAG There is no route match the path [ postcard.getPath() ], in group [ postcard.getGroup() ]);} else {// Load route and cache it into memory, then delete from metas.try {if (ARouter.debuggable()) {logger.debug(TAG, String.format(Locale.getDefault(), The group [%s] starts loading, trigger by [%s], postcard.getGroup(), postcard.getPath()));}IRouteGroup iGroupInstance groupMeta.getConstructor().newInstance();iGroupInstance.loadInto(Warehouse.routes);Warehouse.groupsIndex.remove(postcard.getGroup());if (ARouter.debuggable()) {logger.debug(TAG, String.format(Locale.getDefault(), The group [%s] has already been loaded, trigger by [%s], postcard.getGroup(), postcard.getPath()));}} catch (Exception e) {throw new HandlerException(TAG Fatal exception when loading group meta. [ e.getMessage() ]);}completion(postcard); // Reload} else {//找到路由信息后则将配置的路由信息填充到Postcard对象中postcard.setDestination(routeMeta.getDestination());//要跳转 Activity.class 路径postcard.setType(routeMeta.getType());postcard.setPriority(routeMeta.getPriority());postcard.setExtra(routeMeta.getExtra());Uri rawUri postcard.getUri();if (null ! rawUri) { //这里主要是完成参数的填充}//针对不同的路由类型进行处理switch (routeMeta.getType()) {case PROVIDER: //如果是服务提供者则尝试获取其具体实例如果没有则根据路由信息构造一个实例初始化并存储到数据仓库Class? extends IProvider providerMeta (Class? extends IProvider) routeMeta.getDestination();IProvider instance Warehouse.providers.get(providerMeta);if (null instance) { // Theres no instance of this providerIProvider provider;provider providerMeta.getConstructor().newInstance();provider.init(mContext);Warehouse.providers.put(providerMeta, provider);instance provider;}postcard.setProvider(instance);//服务提供者被设置成绿色渠道不用接受拦截检查postcard.greenChannel(); break;case FRAGMENT://fragment也不用拦截检查postcard.greenChannel(); default:break;}}//_ARouter#_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()) {//是 ACTIVITY 数据填充到intent并且调用 startActivitycase ACTIVITY:final Intent intent new Intent(currentContext, postcard.getDestination());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);}// Set ActionsString action postcard.getAction();if (!TextUtils.isEmpty(action)) {intent.setAction(action);}// Navigation in main looper.runInMainThread(new Runnable() {Overridepublic void run() {startActivity(requestCode, currentContext, intent, postcard, callback);}});break;//PROVIDER类型则直接返回其服务提供者case PROVIDER:return postcard.getProvider();//如果是BOARDCAST 、 CONTENT_PROVIDER 、 FRAGMENT则创建其需要的实体并填充数据返回对象 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;}上面的初始化代码其实就可以了解其原理下面我们可以画出时序图了解大致流程。
四、总结
ARouter 通过 apt 技术生成保存路径(路由path)和被注解(Router)的组件类的映射关系的类利用这些保存了映射关系的类根据用户的请求 postcard明信片寻找到要跳转的目标地址(class),使用 Intent 跳转。 ARouter的重要性主要体现在以下几个方面
模块化开发随着软件规模和复杂度的增加越来越多的应用程序采用模块化开发方式。ARouter支持跨模块的调用简化了模块间跳转的复杂度降低了耦合性提升了整个应用的可维护性和可扩展性。代码解耦在传统的Activity跳转方式中一般是通过Intent来传递参数不同页面之间的参数传递比较麻烦还有可能导致代码冗余。ARouter采用注解方式传递参数简化了代码的编写和阅读。动态路由路由是基于注解方式实现的可以在代码中动态注册和删除路由。ARouter还支持路由重定向、降级等高级功能可以根据不同的业务场景灵活处理路由逻辑。统一管理ARouter提供了统一管理路由配置的界面可以直览整个项目的路由规则方便开发人员进行维护和管理。
ARouter是一款非常实用的路由框架可以帮助开发者在模块化开发、代码解耦、动态路由和统一管理等方面提高开发效率和应用质量。
下面整理了《Android 架构学习手册》《深入理解Gradle框架》学习笔记根据自己学习中所做的一些笔录来整的主要也是方便后续好复习翻阅省掉在去网上查找的时间以免在度踩坑如果大家有需要的可以直接 通过点击此处↓↓↓ 进行参考学习https://qr21.cn/CaZQLo?BIZECOMMERCE
Android 架构学习手册
深入理解Gradle框架
- 上一篇: 珠海网站建设技术外包玉林网站设计
- 下一篇: 珠海网站建设哪个平台好产品推广方案范例
相关文章
-
珠海网站建设技术外包玉林网站设计
珠海网站建设技术外包玉林网站设计
- 技术栈
- 2026年03月21日
-
珠海网站公司哪家好提升访问境外网站速度
珠海网站公司哪家好提升访问境外网站速度
- 技术栈
- 2026年03月21日
-
珠海特价做网站郑州 高端网站建设
珠海特价做网站郑州 高端网站建设
- 技术栈
- 2026年03月21日
-
珠海网站建设哪个平台好产品推广方案范例
珠海网站建设哪个平台好产品推广方案范例
- 技术栈
- 2026年03月21日
-
珠海网站建设培训xampp上传Wordpress
珠海网站建设培训xampp上传Wordpress
- 技术栈
- 2026年03月21日
-
珠海网站建设培训北京网站建设管庄
珠海网站建设培训北京网站建设管庄
- 技术栈
- 2026年03月21日
