我为什么用TheRouter而不玩Arouter了呢
TheRouter 简介
TheRouter是货拉拉开源的路由框架,针对Android平台实现组件化、跨模块调用、动态化等功能的集成框架。
TheRouter 掘金:juejin.cn/post/713971…
Github: github.com/HuolalaTech…
官网:therouter.cn/
为什么要用TheRouter
功能 | TheRouter | ARouter | WMRouter |
---|---|---|---|
Fragment路由 | ✔️ | ✔️ | ✔️ |
支持依赖注入 | ✔️ | ✔️ | ✔️ |
加载路由表 | 无运行时扫描无反射 | 运行时扫描dex反射实例类性能损耗大 | 运行时读文件反射实例类性能损耗中 |
注解正则表达式 | ✔️ | ✖️ | ✔️ |
Activity指定拦截器 | ✔️(四大拦截器可根据业务定制) | ✖️ | ✔️ |
导出路由文档 | ✔️(路由文档支持添加注释描述) | ✔️ | ✖️ |
动态注册路由信息 | ✔️ | ✔️ | ✖️ |
APT支持增量编译 | ✔️ | ✔️(开启文档生成则无法增量编译) | ✖️ |
plugin支持增量编译 | ✔️ | ✖️ | ✖️ |
多 Path 对应同一页面(低成本实现双端path统一) | ✔️ | ✖️ | ✖️ |
远端路由表下发 | ✔️ | ✖️ | ✖️ |
支持单模块独立初始化 | ✔️ | ✖️ | ✖️ |
支持使用路由打开第三方库页面 | ✔️ | ✖️ | ✖️ |
上图是从官方获取的介绍,结合自己使用,从以下几点介绍他的好处。
- 使用简易
- 针对后台startActivity的兼容处理
- 直接获取Intent对象
- 动态下发路由表的骚操作
- 和Arouter性能相比
- 使用简易
针对刚入手的同学,很多同学其实需要的功能不多,主要就是跳转页面,原先使用过的Arouter,也能快速适应。想深入学习更多的同学可以再去官网或者官方掘金see see
// 简单的传参和路由跳转
TheRouter.build("test://webview/home")
.withString("url", "http://www.baidu.com")
.navigation(act)
// 如果要打开的是fragment,需要使用 .createFragment();
- 针对后台startActivity的兼容处理
Android 10 (级别 29) 及更高版本对后台应用可启动 Activity 的时间施加限制。这些限制有助于最大限度地减少对用户造成的中断(可以更省电),并且可以让用户更好地控制其屏幕上显示的内容。
官方针对Android10以及以上版本调用startActivity的限制,也就是在后台调用该方法是无法跳转的,TheRoute提供兼容处理,先暂停跳转,等APP重新启动了再继续跳转。
// 以下代码只是功能介绍,大家按需自取
// 后台跳转页面
fun goBackActivity(activity: Activity) {
val navigator: Navigator =
TheRouter.build("test://webview/home")
.withString("paramStr", paramStr)
.withInt("paramInt", 0)
if (AndroidVersion.hasQ() && !AppUtils.isAppForeground()) {
// pending() 会标记存入集合LinkedList
navigator.pending().navigation(activity)
} else {
navigator.navigation(activity)
}
}
// Application监听
class ApplicationObserver : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
// 应用重进onResume,把原先pending()存入集合的navigation,重新取出全部执行
// sendPendingNavigator是Navigator的顶级函数
sendPendingNavigator()
}
}
- 直接获取Intent对象
大部分的路由框架都不提供直接返回Intent,但是有时候我们又只需要对应其他模块的intent对象并不需要跳转,例如构建系统通知栏的点击需要传入PendingIntent,可能需要通过Intent对象构建。
// 获取intent
val intent = TheRouter.build("test://login/hello").createIntent(activity)
- 动态下发路由表的『骚操作』
为什么我个人说这是『骚操作』呢?我们以前写一个页面,页面崩溃了,那么我们就想办法修复,让用户先忍忍。可是用你这个APP的人真的能忍受你的崩溃吗?答案是不能的,因此我们想尽各种办法例如热修复等等,但是还是有没有经过热修复的人崩溃了,还是大面积的崩溃。
那动态下发路由表,让这个崩溃页面的路由改下其他页面,例如这个崩溃页面的路由跳转H5页面,告知用户正在紧急修复,这样的过渡会比直接崩溃使用感受好。
当然不止这个场景,再举例一个我们最常见的,例如A页面忘了给相机权限,然后上线了跳转A页面的时候才发现少了这个权限,咋整?重发版呗。但是如果用TheRouter,可以在原工程预留一个过渡页面,我们动态下发路由表,跳到这个过渡页获取权限了再重新跳转原来A页面。
// 获取远端的路由map
/**
[
{
"path": "test://home/webview/pre",
"action": "test://action/start_activity?path=test://app/alert?type=-1&permissionJson={"android.permission.READ_PHONE_STATE": "需要获取您的手机网络状态"}",
"description": "",
"className": "com.test.main.PreWebViewV2Activity",
"params": {
}
}
]
// action说明: 可以写一个test://app/alter权限弹窗页面,传入permissionJson参数授权,授权成功之后再重新执行原来的路由地址
*/
fun getServiceRouterMap() {
try {
val gson = "注释提供的格式"
if (gson.isNullOrEmpty()) {
return
}
Kv.putEnv(LOCAL_ROUTER_MAP, gson) // 本地存储,方便下次取出
mRouteItem = GsonUtils.fromJson(gson, object : TypeToken?>() {}.type)
} catch (e: Exception) {
Log.d("updateRouterMap", e?.toString())
}
}
// 把远端路由遍历添加到本地
fun addMdapRouteMap() {
Log.d("HllMarsConfigTask", "asyncInitRouteMap")
var list = mRouteItem
if (list != null && list.size > 0) {
// 建议远端下发路由表差异部分,用远端包覆盖本地更合理
addRouteMap(list) // TheRouter库RouteMap.kt提供顶级函数
}
}
// 以下是TheRouter库RouteMap.kt类
// 具体实现:如何把远端路由添加到本地
@Synchronized
fun addRouteMap(routeItemArray: Collection?) {
if (routeItemArray != null && !routeItemArray.isEmpty()) {
for (entity in routeItemArray) {
addRouteItem(entity)
}
}
}
@Synchronized
fun addRouteItem(routeItem: RouteItem) {
var path = routeItem.path
if (path.endsWith("/")) {
path = path.substring(0, path.length - 1)
}
debug("addRouteItem", "add $path")
ROUTER_MAP[path] = routeItem
onRouteMapChangedListener?.onChanged(routeItem)
}
- 和Arouter性能相比
以阿里的Arouter来说,它是有比较沉重的历史包袱,虽然后面有迭代几个版本来优化,但是更多的还是在历史基础上优化,TheRouter却没有历史包袱。下面是我们自己工程跑的对比效果
链接:https://juejin.cn/post/7148639882401808391
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。