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; }
关于自定义注解的详细介绍,请阅读我的文章。这里不再多说。
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),这里只是介绍了一个思路,有好的建议欢迎交流,一起进步。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
vue-router判断页面未登录自动跳转到登录页的方法示例
-
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
-
Router解决跨模块下的页面跳转示例
-
vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法
-
路由跳转,router-view不显示组件页面的几个可能出现的问题及解决方案
-
Router解决跨模块下的页面跳转
-
vue-router判断页面未登录自动跳转到登录页的方法示例
-
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
-
Router解决跨模块下的页面跳转示例
-
如何解决Router跨模块跳转问题