TheRouter 簡介
??TheRouter是貨拉拉開源的路由框架雷恃,針對Android平臺實(shí)現(xiàn)組件化健民、跨模塊調(diào)用柳恐、動態(tài)化等功能的集成框架憾朴。
TheRouter 掘金:https://juejin.cn/post/7139718803637665822
Github: https://github.com/HuolalaTech/hll-wp-therouter-android
官網(wǎng):https://therouter.cn/
為什么要用TheRouter
功能 | TheRouter | ARouter | WMRouter |
---|---|---|---|
Fragment路由 | ?? | ?? | ?? |
支持依賴注入 | ?? | ?? | ?? |
加載路由表 | 無運(yùn)行時(shí)掃描無反射 | 運(yùn)行時(shí)掃描dex反射實(shí)例類性能損耗大 | 運(yùn)行時(shí)讀文件反射實(shí)例類性能損耗中 |
注解正則表達(dá)式 | ?? | ?? | ?? |
Activity指定攔截器 | ??(四大攔截器可根據(jù)業(yè)務(wù)定制) | ?? | ?? |
導(dǎo)出路由文檔 | ??(路由文檔支持添加注釋描述) | ?? | ?? |
動態(tài)注冊路由信息 | ?? | ?? | ?? |
APT支持增量編譯 | ?? | ??(開啟文檔生成則無法增量編譯) | ?? |
plugin支持增量編譯 | ?? | ?? | ?? |
多 Path 對應(yīng)同一頁面(低成本實(shí)現(xiàn)雙端path統(tǒng)一) | ?? | ?? | ?? |
遠(yuǎn)端路由表下發(fā) | ?? | ?? | ?? |
支持單模塊獨(dú)立初始化 | ?? | ?? | ?? |
支持使用路由打開第三方庫頁面 | ?? | ?? | ?? |
上圖是從官方獲取的介紹狸捕,結(jié)合自己使用,從以下幾點(diǎn)介紹他的好處众雷。
- 使用簡易
- 針對后臺startActivity的兼容處理
- 直接獲取Intent對象
- 動態(tài)下發(fā)路由表的騷操作
- 和Arouter性能相比
- 使用簡易
??針對剛?cè)胧值耐瑢W(xué)灸拍,很多同學(xué)其實(shí)需要的功能不多,主要就是跳轉(zhuǎn)頁面砾省,原先使用過的Arouter鸡岗,也能快速適應(yīng)。想深入學(xué)習(xí)更多的同學(xué)可以再去官網(wǎng)或者官方掘金see see
// 簡單的傳參和路由跳轉(zhuǎn)
TheRouter.build("test://webview/home")
.withString("url", "http://www.baidu.com")
.navigation(act)
- 針對后臺startActivity的兼容處理
Android 10 (級別 29) 及更高版本對后臺應(yīng)用可啟動 Activity 的時(shí)間施加限制编兄。這些限制有助于最大限度地減少對用戶造成的中斷(可以更省電)轩性,并且可以讓用戶更好地控制其屏幕上顯示的內(nèi)容。
??官方針對Android10以及以上版本調(diào)用startActivity的限制翻诉,也就是在后臺調(diào)用該方法是無法跳轉(zhuǎn)的炮姨,TheRoute提供兼容處理捌刮,先暫停跳轉(zhuǎn)碰煌,等APP重新啟動了再繼續(xù)跳轉(zhuǎn)。
// 以下代碼只是功能介紹绅作,大家按需自取
// 后臺跳轉(zhuǎn)頁面
fun goBackActivity(activity: Activity) {
val navigator: Navigator =
TheRouter.build("test://webview/home")
.withString("paramStr", paramStr)
.withInt("paramInt", 0)
if (AndroidVersion.hasQ() && !AppUtils.isAppForeground()) {
// pending() 會標(biāo)記存入集合LinkedList
navigator.pending().navigation(activity)
} else {
navigator.navigation(activity)
}
}
// Application監(jiān)聽
class ApplicationObserver : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
// 應(yīng)用重進(jìn)onResume芦圾,把原先pending()存入集合的navigation,重新取出全部執(zhí)行
// sendPendingNavigator是Navigator的頂級函數(shù)
sendPendingNavigator()
}
}
- 直接獲取Intent對象
??大部分的路由框架都不提供直接返回Intent俄认,但是有時(shí)候我們又只需要對應(yīng)其他模塊的intent對象并不需要跳轉(zhuǎn)个少,例如構(gòu)建系統(tǒng)通知欄的點(diǎn)擊需要傳入PendingIntent,可能需要通過Intent對象構(gòu)建。
// 獲取intent
val intent = TheRouter.build("test://login/hello").createIntent(activity)
- 動態(tài)下發(fā)路由表的『騷操作』
?? 為什么我個(gè)人說這是『騷操作』呢眯杏?我們以前寫一個(gè)頁面夜焦,頁面崩潰了,那么我們就想辦法修復(fù)岂贩,讓用戶先忍忍茫经。可是用你這個(gè)APP的人真的能忍受你的崩潰嗎萎津?答案是不能的卸伞,因此我們想盡各種辦法例如熱修復(fù)等等,但是還是有沒有經(jīng)過熱修復(fù)的人崩潰了锉屈,還是大面積的崩潰荤傲。
??那動態(tài)下發(fā)路由表,讓這個(gè)崩潰頁面的路由改下其他頁面颈渊,例如這個(gè)崩潰頁面的路由跳轉(zhuǎn)H5頁面遂黍,告知用戶正在緊急修復(fù)终佛,這樣的過渡會比直接崩潰使用感受好。
??當(dāng)然不止這個(gè)場景雾家,再舉例一個(gè)我們最常見的查蓉,例如A頁面忘了給相機(jī)權(quán)限,然后上線了跳轉(zhuǎn)A頁面的時(shí)候才發(fā)現(xiàn)少了這個(gè)權(quán)限榜贴,咋整豌研?重發(fā)版唄。但是如果用TheRouter,可以在原工程預(yù)留一個(gè)過渡頁面唬党,我們動態(tài)下發(fā)路由表鹃共,跳到這個(gè)過渡頁獲取權(quán)限了再重新跳轉(zhuǎn)原來A頁面。
// 獲取遠(yuǎn)端的路由map
/**
[
{
"path": "test://home/webview/pre",
"action": "test://action/start_activity?path=test://app/alert?type=-1&permissionJson={"android.permission.READ_PHONE_STATE": "需要獲取您的手機(jī)網(wǎng)絡(luò)狀態(tài)"}",
"description": "",
"className": "com.test.main.PreWebViewV2Activity",
"params": {
}
}
]
// action說明: 可以寫一個(gè)test://app/alter權(quán)限彈窗頁面驶拱,傳入permissionJson參數(shù)授權(quán)霜浴,授權(quán)成功之后再重新執(zhí)行原來的路由地址
*/
fun getServiceRouterMap() {
try {
val gson = "注釋提供的格式"
if (gson.isNullOrEmpty()) {
return
}
Kv.putEnv(LOCAL_ROUTER_MAP, gson) // 本地存儲,方便下次取出
mRouteItem = GsonUtils.fromJson(gson, object : TypeToken<List<RouteItem?>?>() {}.type)
} catch (e: Exception) {
Log.d("updateRouterMap", e?.toString())
}
}
// 把遠(yuǎn)端路由遍歷添加到本地
fun addMdapRouteMap() {
Log.d("HllMarsConfigTask", "asyncInitRouteMap")
var list = mRouteItem
if (list != null && list.size > 0) {
// 建議遠(yuǎn)端下發(fā)路由表差異部分蓝纲,用遠(yuǎn)端包覆蓋本地更合理
addRouteMap(list) // TheRouter庫RouteMap.kt提供頂級函數(shù)
}
}
// 以下是TheRouter庫RouteMap.kt類
// 具體實(shí)現(xiàn):如何把遠(yuǎn)端路由添加到本地
@Synchronized
fun addRouteMap(routeItemArray: Collection<RouteItem>?) {
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來說阴孟,它是有比較沉重的歷史包袱,雖然后面有迭代幾個(gè)版本來優(yōu)化税迷,但是更多的還是在歷史基礎(chǔ)上優(yōu)化永丝,TheRouter卻沒有歷史包袱。下面是我們自己工程跑的對比效果