Router解决跨模块下的页面跳转示例


Posted in Javascript onJanuary 11, 2018

一、前言

开始模块化开发项目之后,一个很重要的问题就是页面见的跳转问题。

关于模块化发开,可详见我的另一片文章 Android模块化开发探索 。

正是由于将项目模块化拆分,各模块之间没有任何依赖关系,也互相不可见,那么从A模块的a界面跳转到B模块的b界面该怎么办呢?

二、跨模块跳转的方法

这里我们会先介绍这几种常见的跳转方法:

  1. 显示跳转
  2. 隐示跳转
  3. Scheme协议跳转
  4. 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实现跳转。

Router解决跨模块下的页面跳转示例

五、代码实现

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),这里只是介绍了一个思路,有好的建议欢迎交流,一起进步。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
动态改变textbox的宽高的js
Oct 26 Javascript
ASP.NET jQuery 实例4(复制TextBox的文本到本地剪贴板上)
Jan 13 Javascript
jquery text(),val(),html()方法区别总结
Nov 04 Javascript
有关Promises异步问题详解
Nov 13 Javascript
JS简单实现String转Date的方法
Mar 02 Javascript
Angular懒加载机制刷新后无法回退的快速解决方法
Aug 30 Javascript
js处理包含中文的字符串实例
Oct 11 Javascript
JS实现的视频弹幕效果示例
Aug 17 Javascript
vue+mousemove实现鼠标拖动功能(拖动过快失效问题解决方法)
Aug 24 Javascript
移动端H5页面返回并刷新页面(BFcache)的方法
Nov 06 Javascript
基于vue的tab-list类目切换商品列表组件的示例代码
Feb 14 Javascript
react 原生实现头像滚动播放的示例
Apr 21 Javascript
vuex 使用文档小结篇
Jan 11 #Javascript
js判断传入时间和当前时间大小实例(超简单)
Jan 11 #Javascript
js点击时关闭该范围下拉菜单之外的菜单方法
Jan 11 #Javascript
纯js代码生成可搜索选择下拉列表的实例
Jan 11 #Javascript
web前端vue之vuex单独一文件使用方式实例详解
Jan 11 #Javascript
vue-cli webpack 引入jquery的方法
Jan 10 #jQuery
JS计算两个时间相差分钟数的方法示例
Jan 10 #Javascript
You might like
PHP的可变变量名的使用方法分享
2012/02/05 PHP
完美解决令人抓狂的zend studio 7代码提示(content Assist)速度慢的问题
2013/06/20 PHP
php文件读取方法实例分析
2015/06/20 PHP
ThinkPHP框架表单验证操作方法
2017/07/19 PHP
thinkPHP框架乐观锁和悲观锁实例分析
2019/10/30 PHP
Javascript select控件操作大全(新增、修改、删除、选中、清空、判断存在等)
2008/12/19 Javascript
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
Javascript实现多彩雪花从天降散落效果的方法
2015/02/02 Javascript
js实现简单的验证码
2015/12/25 Javascript
jQuery UI插件实现百度提词器效果
2016/11/21 Javascript
js代码实现下拉菜单【推荐】
2016/12/15 Javascript
JS仿Base.js实现的继承示例
2017/04/07 Javascript
微信小程序tabbar不显示解决办法
2017/06/08 Javascript
vue 组件内获取actions的response方式
2019/11/08 Javascript
vue开发移动端底部导航条功能
2020/04/08 Javascript
uni-app如何页面传参数的几种方法总结
2020/04/28 Javascript
浅谈Vuex的this.$store.commit和在Vue项目中引用公共方法
2020/07/24 Javascript
[04:27]DOTA2官方论坛水友赛集锦
2013/09/16 DOTA
[35:26]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第三局
2016/02/26 DOTA
Python实现感知机(PLA)算法
2017/12/20 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
Python sklearn KFold 生成交叉验证数据集的方法
2018/12/11 Python
python实现多进程通信实例分析
2019/09/01 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
Kmeans均值聚类算法原理以及Python如何实现
2020/09/26 Python
CSS3实现时间轴特效
2020/11/02 HTML / CSS
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
德国高性价比网上药店:medpex
2017/07/09 全球购物
白俄罗斯在线大型超市:e-dostavka.by
2019/07/25 全球购物
美国家庭鞋店:Shoe Sensation
2019/09/27 全球购物
逃课上网检讨书
2014/02/20 职场文书
清明节网上祭英烈活动总结
2014/04/30 职场文书
大一新生检讨书
2014/10/29 职场文书
2014年团支部工作总结
2014/11/17 职场文书
虎兄虎弟观后感
2015/06/12 职场文书
创业计划书之面包店
2019/09/12 职场文书