模块化开发项目中页面跳转问题很重要,本文主要介绍了Router解决跨模块下的页面跳转示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。
一、前言
开始模块化开发项目之后,一个很重要的问题就是页面见的跳转问题。
关于模块化发开,可详见我的另一片文章 Android模块化开发探索 。
正是由于将项目模块化拆分,各模块之间没有任何依赖关系,也互相不可见,那么从A模块的a界面跳转到B模块的b界面该怎么办呢?
二、跨模块跳转的方法
这里我们会先介绍这几种常见的跳转方法:
显示跳转
隐示跳转
Scheme协议跳转
Router路由表方案
2.1 显示跳转
显示跳转即我们最最常用的跳转方法:使用Intent,传入当前Activity上下文,和目标Activity的class对象即可,如下:
Intent intent = new Intent(); intent.setClass(mContext, GuideActivity.class); startActivity(intent);
显然,这种方法只能是目标Activity可见(Activity在同一个Module下)的时候才可以这样调用。不适合跨模块间的跳转。
2.2 隐示跳转
我们这里说的隐示跳转,intent不设置class,而是设置Action或者Category。
例如:
在清单文件中
<!--网页展示界面--> <activity android:name="com.whaty.base.BaseWebViewActivity" android:hardwareAccelerated="true"> <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="com.whaty.base.BaseWebViewActivity" /> </intent-filter> </activity>
跳转时:
//创建一个隐式的 Intent 对象:Action 动作 Intent intent = new Intent(); //设置 Intent 的动作为清单中指定的action intent.setAction("com.whaty.base.BaseWebViewActivity"); startActivity(intent);
2.3 scheme跳转
如果我们为 B 页面定义一个 URI - wsc://home/bbb,然后把共享的 messageModel 拍平序列化成 Json 串,那么 A 只需要拼装一个符合 B 页面 scheme 的跳转协议就可以了。 wsc://home/bbb?message={ “name”:”John”, “age”:31, “city”:”New York” }
在清单文件中,配置data属性,设置其host、path、scheme等
<activity android:name=".ui.BbbActivity" <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="android.intent.action.VIEW" /> <data android:host="bbb" android:path="/home" android:scheme="wsc" /> </intent-filter> </activity>
跳转时:
final Uri uri = new Uri.Builder().authority("wsc").path("home/bbb").appendQueryParameter("message", new Gson().toJson(messageModel)).build(); final Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(uri); startActivity(intent);
以上的方法,都不是我们想要的,接下来开始介绍我们的Router方案。
三、为什么要用Router
Google提供了显式和隐式两种原生路由方案。但在模块化开发中,显式Intent存在类直接依赖的问题,造成模块间严重耦合。隐式Intent则需要在Manifest中配置大量路径,导致难以拓展(如进行跳转拦截)。为了解决以上问题,我们需要采用一套更为灵活的Router方案。
四、实现思路
思路是这样的:
使用注解,为每个目标Activity标注别名。在应用启动时,对所有类进行扫名,将注解过的Activity存于路由表中。
跳转时,在路由表中通过别名获取目标Activity的class对象,使用Intent实现跳转。
五、代码实现
5.1 自定义注解
/** * Description: 路由跳转界面 注解 * Created by jia on 2018/1/10. * 人之所以能,是相信能 */ @Target(ElementType.TYPE) //注解作用于类型(类,接口,注解,枚举) @Retention(RetentionPolicy.RUNTIME) //运行时保留,运行中可以处理 @Documented // 生成javadoc文件 public @interface Action { String DEFAULT = "js"; String value() default DEFAULT; }
关于自定义注解的详细介绍,请阅读我的文章java进阶之自定义注解。这里不再多说。
5.2 注解Activity
@Action("MainActivity") public class MainActivity extends BaseActivity implements TabLayout.OnTabSelectedListener { ... }
在创建Activity时,用刚刚自定义的注解进行注解,为其注释别名。
5.3 启动时扫描
private void getAllActivities(Context ctx){ try { //通过资源路径获得DexFile DexFile e = new DexFile(ctx.getPackageResourcePath()); Enumeration entries = e.entries(); //遍历所有元素 while(entries.hasMoreElements()) { String entryName = (String)entries.nextElement(); //匹配Activity包名与类名 if(entryName.contains("activity") && entryName.contains("Activity")) { //通过反射获得Activity类 Class entryClass = Class.forName(entryName); if(entryClass.isAnnotationPresent(Action.class)) { Action action = (Action)entryClass.getAnnotation(Action.class); this.map.put(action.value(), entryClass); } } } } catch (Exception e) { e.printStackTrace(); } }
在应用启动时,Application中对包下的所有类进行扫描,先找到名字中到activity的(定义到activity包下),并将带有注解标注的Activity,存入map中。
5.4 跳转
/** * 页面跳转 * @param activity * @param alias */ public void jumpActivity(Activity activity, String alias) throws ClassNotFoundException{ if(map.containsKey(alias)) { Intent intent = new Intent(activity, map.get(alias)); activity.startActivity(intent); } else { throw new ClassNotFoundException(); } }
跳转的时候传入目标Activity的别名即可(这里的别名就是注解的别名)。
总结
通过这种方式,解决了跳转Activity所产生的的模块依赖问题,相较于原生方案,拓展性更强。但这种方案只是阶段性的,还存在一些问题。首先,加载过程中,频繁使用到反射,会产生性能问题。其次,对于每个Activity的别名,需要进行统一维护,增加了协作成本。还有待优化。
当然,市面上有很多流行的Router方案(如阿里的ARouter),这里只是介绍了一个思路,有好的建议欢迎交流,一起进步。
相关推荐:
以上是Router解决跨模块下的页面跳转的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver Mac版
视觉化网页开发工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能