Router的定义
路由,简单的来说就是映射页面直接跳转关系的。需要注意的是,这个映射关系需要在App启动的时候建立好。
Router的优点
- 解耦合:这个是最直观的。之前我们需要引入目标页面的Activity.class现在这些不需要要了。
 - 自由配置:这个是为了方便产品或者运维的。我们事先定义好页面的映射关系,那么运营就可以通过后台配置他想跳转的页面了。
 - 模块化:随着业务逐渐增多,就需要模块化。模块化的前提是解决页面之前的依赖关系,也就是前面说的解耦合。
 - KSRouter可以通过RouterConfig对象配置多个域名。
 - KSRouter支持在目标页面使用注解的方式取值。
 - KSRouter想对于之前的Router方案来说去除了配置参数的类型。
 - KSRouter将用户相关的操作(登录等)抛出到具体应用内部去处理,KSRouter库不做处理。
 - KSRouter将WebView相关操作(cookie等)抛出到具体应用内部去处理,KSRouter库不做处理.
 
初始化Router
1  | RouterConfig config = new RouterConfig.Builder()  | 
通过Builder的方式创建RouterConfig。Host的配置可以是多个,比如有网页形式的https://开头的,也有本地形式的ksrouter开头的。拦截器首先通过BrowserRouterInterceptor拦截器,如果没有匹配到规则,默认会走内部WebView的方式打开。当然,如果匹配到了,走到UserRouterInterceptor中会拦截到当前打开的页面需不需要登录,如果需要登录并且当前用户还没有登录的情况下。此拦截器内部会直接跳转登录页面。否则会进入InnerRouterInterceptor这个拦截器当中。
简单用法
跳转到下一个页面
1  | //当前页面  | 
跳转到下一个页面并携带参数
跳转代码如下:1
2
3
4
5Map<String, Object> map = new HashMap<>();
map.put(RouterConstant.IntentKey.NAME, "wuchuang");
map.put(RouterConstant.IntentKey.AGE, 17);
map.put(RouterConstant.IntentKey.SERIALIZABLE, new TestEntity("entity_name",12));
KSRouter.getInstance().open(context, RouterConstant.NEXT_WITH_PARAMS, map);
目标页面代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17(value = RouterConstant.NEXT_WITH_PARAMS)
public class NextWithParamsActivity extends BaseActivity {
    
    public void initView() {
        super.initView();
        setTitle("NextWithParams");
        final String name = getIntent().getStringExtra(RouterConstant.IntentKey.NAME);
        final int age = getIntent().getIntExtra(RouterConstant.IntentKey.AGE, 0);
        final TestEntity entity = getIntent().getSerializableExtra(RouterConstant.IntentKey.SERIALIZABLE);
        //TODO
    }
    
    public int getLayoutId() {
        return R.layout.activity_next_with_params;
    }
}
当然,如果你觉得getIntent().getXXXExtra()太繁琐,也可以通过@RouterPatams的方式获取
1  | (value = RouterConstant.NEXT_WITH_PARAMS)  | 
RouterParams注册使用的前提需要在Activity中调用KSRouter的inject方法注入,这个步骤可以放在BaseActivity中,或者放在ActivityLifecycleCallbacks中来完成都是可以的。
其他Router功能
通过一个接口来展示Router功能1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45/**
 * 初始化
 */
void initialize(Context context, RouterConfig routerConfig);
/**
 * Router注入
 * @param activity
 */
void inject(Activity activity);
/**
 * 用于WebView打开App页面(可携带参数)
 */
RouterInfo openWithWeb(Context context, String url);
 
/**
 * 用于WebView打开App页面(可携带参数)
 */
RouterInfo openForResultWithWeb(Context context, String url);
/**
 * App内部打开App页面(不带参数)
 */
RouterInfo open(Context context, String path);
/**
 * App内部打开App页面(带参数)
 */
RouterInfo open(Context context, String path, Map<String, Object> params);
/**
 * App内部打开App页面并且需要返回结果(不带参数)
 */
RouterInfo openForResult(Context context, String path, int requestCode);
/**
 * App内部打开App页面并且需要返回结果(带参数)
 */
RouterInfo openForResult(Context context, String path, Map<String, Object> params, int requestCode);
/**
 * 获取当前路由的Path
 */
String getCurrentPath(Class cls);
源码解析
定义RouterInfo
如何定义页面直接的映射和跳转关系,可以从一个实体类中看出。1
2
3
4
5
6
7public class RouterInfo implements Cloneable{
    private List<String> paths;
    private String activityCls;
    private Map<String, Object> paramsMap;
    private int requestCode;
    private String currentPath;
}
paths包含了一个一对多的关系,也就是说一个页面可以存在多个Path,不同的Path只要在当前页面声明过都可以跳转到这个页面。
activityCls是用原生Intent跳转是所需要的参数。
paramsMap为页面跳转所携带的数据。如果页面通过startActivityForResult形式,那么requestCode是必不可少的参数。
currentPath可以获取当前跳转页面对应的Path,用来处理Activity内部多个Fragment跳转的场景。
InnerRouterInterceptor
1  | 
  | 
注:根据requestCode来判断是否需要返回结果给前一个Activity,通过isAssignableFrom方法来确定当前参数的类型[常用的基本数据类型,Serializable或者Parcelable数据]。并按照指定类型放入Intent中。
和老版本对比
HOST或者说是协议的添加
比如首页的Router配置信息如下:1
2
3
4({
        BuildConfig.dai + "/finance", BuildConfig.dai + "/project/list", BuildConfig.dai + "/creditassign/list", BuildConfig.dai + "/discovery", BuildConfig.dai + "/user",
        BuildConfig.www + "/finance", BuildConfig.www + "/project/list", BuildConfig.www + "/creditassign/list", BuildConfig.www + "/discovery", BuildConfig.www + "/user"
})
KSRouter中只需要这样写1
2
3({
        "/finance", "/project/list", "/creditassign/list", "/discovery",  "/user"
})
Router注解不提供参数类型
比如充值页面Router配置信息如下:1
(value = BuildConfig.passport + "/user/recharge", floatParams = "rechargenum", transfer = "amount=>rechargenum", booleanParams = "skip_result_act")
注:不配置参数类型也是可以获取到数据。
KSRouter中只需要这样写1
("/user/recharge")
目标页面参数的名称转换
比如充值页面Router配置信息如下:1
(value = BuildConfig.passport + "/user/recharge", floatParams = "rechargenum", transfer = "amount=>rechargenum", booleanParams = "skip_result_act")
KSRouter中只需要这样写1
2
3
4
5("amount")
float rechargenum;
或者
float amount;
首先寻找注解上对应的key,如果不存在,就会拿当前字段的名称当做key来取值。