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
"/user/recharge", floatParams = "rechargenum", transfer = "amount=>rechargenum", booleanParams = "skip_result_act") (value = BuildConfig.passport +
注:不配置参数类型也是可以获取到数据。
KSRouter中只需要这样写1
"/user/recharge") (
目标页面参数的名称转换
比如充值页面Router配置信息如下:1
"/user/recharge", floatParams = "rechargenum", transfer = "amount=>rechargenum", booleanParams = "skip_result_act") (value = BuildConfig.passport +
KSRouter中只需要这样写1
2
3
4
5"amount") (
float rechargenum;
或者
float amount;
首先寻找注解上对应的key,如果不存在,就会拿当前字段的名称当做key来取值。