通用路由管理工具组件设计
本专题为软件平台路由规则设计 ,不限于移动端 ,涵盖 移动端 、Web 、电脑(桌面) 、手表与手环等智能穿戴 。在 01~06 基础上,抽象出一套跨端可复用 的路由管理组件设计:统一协议、各端适配层、可插拔拦截器与扩展点。软件体系 覆盖 iOS、Android、HarmonyOS、Flutter、MacOS、WinOS、WebApp、ReactNative、WatchOS 及智能穿戴形态,便于在各端保持一致的路由语义与配置,详见 08-软件体系与多平台路由对照。
一、设计目标与原则
1.1 目标
- 协议统一:path、query、navigate 方式(push/replace/present)在各端语义一致。
- 多端适配:同一套「路由表 + 拦截器 + 深链接」逻辑,通过各端适配层落地到具体平台 API。
- 可扩展:支持动态路由表、拦截器链、服务发现、编译期/运行时双轨注册。
- 可观测:统一埋点、耗时与降级入口,便于监控与排障。
1.2 原则
- 单一数据源:路由表(含动态下发)为唯一真实来源,深链接、App 内跳转均解析为 path + params 后查表。
- 平台无关接口:核心接口不依赖 UIKit/Activity/Widget,仅依赖 path、params、result 等抽象。
- 适配器隔离:平台相关实现(如 pushViewController/startActivity/context.go)封装在适配层,核心层只调用「打开目标」「返回结果」等抽象接口。
二、核心抽象与整体架构
2.1 概念模型(思维导图)
2.2 分层架构图
2.3 统一 Path 与参数规范
- Path :建议统一为 绝对路径 ,如
/module/page/detail、/action/share、/service/user;支持动态段,如/detail/:id。 - Query/Params:键值对,字符串为主;复杂对象可序列化为 JSON 或由各端约定类型(如 extra)。
- 路由类型与执行方式 :
- 页面跳转 :
push(压栈)、replace(替换当前)、present(模态),对应打开完整页面。 - 功能唤醒 :
getService(获取服务实例)、invokeAction(执行动作/能力)、openModal(打开弹窗)、openOverlay(打开浮层),不必然改变导航栈或打开整页。
- 页面跳转 :
三、核心接口定义(平台无关)
以下用伪代码 + 各端示例描述,便于在多端实现时对齐语义。
3.1 路由表与路由项
text
RouteItem:
path: string // 如 "/page/detail"、"/action/share"、"/service/user"
pattern?: string // 如 "/page/detail/:id" 用于匹配与参数提取
type: "page" | "service" | "action" | "modal" // 页面跳转 / 服务获取 / 功能动作 / 弹窗浮层
target: PlatformTarget // 由各端适配层解析为页面、服务工厂、Action 回调、弹窗 Builder 等
defaultParams?: Map<string, string>
- page:页面跳转,适配层执行 openPage / replacePage / present。
- service:功能唤醒之服务获取,适配层执行 resolveService,返回实例。
- action:功能唤醒之动作执行,适配层执行 invokeAction(如分享、埋点、业务逻辑),无返回值或返回结果。
- modal:功能唤醒之弹窗/浮层,适配层执行 openModal / openOverlay,不压主栈。
iOS(Swift)示例 :target 可存闭包 () -> UIViewController、() -> Any(服务)、或 ([String: String]) -> Void(Action)。
Android(Kotlin)示例 :target 可为 Class<*>、(Context, Map) -> Intent、或 (Context, Map) -> Any(服务/动作)。
Flutter(Dart)示例 :target 可为 Widget Function(RouteParams)、或 Future<T> Function(RouteParams)(服务/动作)。
3.2 路由表接口
text
IRouteTable:
register(item: RouteItem): void
unregister(path: string): void
merge(items: RouteItem[]): void // 动态下发合并
lookup(path: string, params?: Map): RouteResult? // 返回匹配的 RouteItem + 解析后的 params
RouteResult :{ item: RouteItem, params: Map<string, string>, navigateMode: "push"|"replace"|"present" }。
RouteContext (拦截器与适配器共用):{ path: string, params: Map, result: RouteResult, platformContext: unknown },便于拦截器修改 params 或决定是否中断。
3.3 拦截器接口
text
IRouteInterceptor:
order: number // 越小越先执行
process(context: RouteContext): boolean | Promise<boolean>
onInterrupt?(context: RouteContext): void
RouteContext :包含 path, params, routeResult, platformContext(各端的 Context/Context/BuildContext 等)。
若 process 返回 false 或 reject,则不再执行后续拦截器与目标,并调用 onInterrupt。
3.4 门面接口(Router)
text
IRouter:
// 页面跳转
navigate(path: string, params?: Map, options?: NavigateOptions): Promise<boolean>
replace(path: string, params?: Map): Promise<boolean>
present(path: string, params?: Map): Promise<boolean>
// 功能唤醒
getService<T>(path: string, params?: Map): T | null // 服务获取
invokeAction(path: string, params?: Map): Promise<unknown> // 动作执行,可返回结果
openModal(path: string, params?: Map): Promise<boolean> // 弹窗/浮层
handleOpenURL(url: string | Uri): boolean // 深链接入口,解析后按路由类型分发
NavigateOptions :{ mode: "push"|"replace"|"present", animated?: boolean }。
功能唤醒 与页面跳转共用同一路由表;查表后根据 RouteItem.type 分发到 getService / invokeAction / openModal 或 navigate。
四、各端适配层设计
4.1 适配器接口(平台无关抽象)
text
IPlatformRouterAdapter:
// 页面跳转
openPage(result: RouteResult, platformContext: unknown): void
replacePage(result: RouteResult, platformContext: unknown): void
presentPage(result: RouteResult, platformContext: unknown): void
// 功能唤醒
resolveService(result: RouteResult, platformContext: unknown): unknown | null
invokeAction(result: RouteResult, platformContext: unknown): Promise<unknown>
openModal(result: RouteResult, platformContext: unknown): void // 弹窗/浮层
}
核心层只持有 IPlatformRouterAdapter,在「查找 + 拦截通过」后根据 RouteItem.type 调用对应方法:page → openPage/replacePage/presentPage;service → resolveService;action → invokeAction;modal → openModal。
功能唤醒与页面跳转统一 :同一 path 协议、同一路由表、同一拦截器链;仅根据 RouteItem.type 在适配层走不同分支(打开页面 vs 获取服务 vs 执行动作 vs 打开弹窗),便于运营链路上「一个 path 既可跳转页也可唤醒能力」。
4.2 iOS 适配层要点(Swift)
- openPage :从
RouteResult.item.target得到 ViewController 类型或工厂闭包,创建 VC,取platformContext为当前 top VC,执行navigationController?.pushViewController(vc)或show(vc)。 - replacePage :
setViewControllers或replaceViewController。 - presentPage :
present(vc, animated: true)。 - resolveService:若 target 为协议类型,从容器或模块内获取实现并返回。
- 深链接 :在 AppDelegate/SceneDelegate 中收到 URL 后,解析为 path + query,调用
Router.shared.handleOpenURL(url)。
4.3 Android 适配层要点(Kotlin)
- openPage :
RouteResult中 target 为Class<Activity>或 Intent 工厂;startActivity(Intent(context, target).apply { putExtras(...) })。 - replacePage :
finish()当前再startActivity,或使用 Single Task / 自定义栈。 - presentPage :可对应
startActivity带FLAG_ACTIVITY_NEW_TASK或 Dialog 风格 Activity。 - resolveService:通过路由 path 映射到接口实现类,从模块或 DI 容器获取实例。
- 深链接 :在 MainActivity 的
onNewIntent/onCreate中取intent.data,解析为 path + query,调用Router.handleOpenURL(uri)。
4.4 Flutter 适配层要点(Dart)
- openPage :将
RouteResult.path与 params 拼成go_router的 location,调用context.go(location)或context.push(location);若使用自定义 Navigator 2.0,则更新 state 的 pages 并 notifyListeners。 - replacePage :
context.go或替换栈顶。 - presentPage :
context.push或使用showDialog/命名路由的 modal 语义。 - resolveService:path 映射到 GetIt/Provider 或模块内注册的工厂,返回实例。
- 深链接 :在
app_links的getInitialLink/uriLinkStream中解析 Uri,转为 path + query,调用Router.handleOpenURL(uri)。
4.5 其他平台适配层要点摘要
| 平台 | 适配层要点 |
|---|---|
| HarmonyOS | Want.uri → path/params;router.pushUrl;Ability 与路由表映射。 |
| MacOS | 同 iOS(VC/Window 栈);NSWindow、NSViewController。 |
| WinOS | 协议/启动参数 → path/params;Frame.Navigate 或主窗口导航。 |
| WebApp | path = location.pathname,query = searchParams;History.pushState/replaceState;Vue Router / React Router。 |
| ReactNative | Linking 收 URL → path/params;React Navigation 的 linking 与 navigate。 |
| WatchOS | 简化 path 表;与 iPhone 同步或本地 WKInterfaceController 栈。 |
五、navigate 完整流程时序图
从调用 Router.navigate(path) 到适配器执行打开页面,各层协作顺序如下。
六、数据流与职责划分(泳道图)
七、路由表来源与动态合并(流程图)
- 各端启动时:先加载静态/编译期表,再可选拉取服务端表并
merge(含版本/灰度),最后所有 navigate 均走同一lookup。
八、与深链接、组件化、声明式的衔接
- 深链接 :外部 URL(Scheme 或 Universal Link/App Link)进入 App 后,统一解析为 path + query ,再调用
Router.navigate(path, params)或handleOpenURL,与 App 内跳转共用同一路由表与拦截器。 - 组件化:各模块只依赖「Router + path 协议」,不依赖具体页面类;路由表可由各模块在初始化时 register,或通过编译期生成 + SPI 按需加载。
- 声明式:在 Flutter 侧,适配层可基于 go_router 或自定义 RouterDelegate,由「状态 → pages」驱动;在 iOS/Android 侧,可用「目标栈状态」驱动一次 setViewControllers / 重建 Fragment 栈,与通用 Router 的「navigate/replace」语义对齐。
- 同体系跨端协同 :同一产品在多端(iOS、Android、Web、电脑、手表等)共用同一 path 协议 与路由语义;各端实现各自的 Adapter,但对同一 path 的业务目标一致。这样可实现:一条链接在 Web 打开为 Web 页、在 App 打开为 App 页;手表与手机通过 path 同步实现接力;「在电脑上继续」等跨端续传依赖同一 path+query。设计时需保证路由表/动态配置在体系内统一或按端态下发,path 命名空间与类型(页面/功能唤醒)在体系内一致。
九、目录与模块建议(跨端可对照)
便于多端实现时对齐,建议目录结构(按端拆分实现,接口保持一致):
text
router_core/ # 各端可抽成接口/协议层,或共用文档
- types: RouteItem, RouteResult, RouteContext, NavigateOptions
- IRouteTable, IRouteInterceptor, IRouter, IPlatformRouterAdapter
router_impl/ # 各端实现
- RouteTableImpl
- InterceptorChain
- Router (门面,持有 Table + Chain + Adapter)
router_adapter_ios/
router_adapter_android/
router_adapter_harmonyos/
router_adapter_flutter/
router_adapter_macos/
router_adapter_winos/
router_adapter_web/
router_adapter_reactnative/
router_adapter_watchos/
router_plugin_deeplink/ # 深链接注入与 handleOpenURL
router_plugin_dynamic/ # 动态表拉取与 merge
十、小结
- 通用路由管理组件 通过 统一 path/query、IRouteTable、IRouteInterceptor、IRouter、IPlatformRouterAdapter 抽象,实现「协议统一、多端适配、可扩展」。
- 同时支持页面跳转路由 (openPage/replacePage/presentPage)与功能唤醒路由 (getService、invokeAction、openModal),同一路由表内用
RouteItem.type(page / service / action / modal)区分,深链接与运营链可共用一个 path 既跳页也唤能力。 - 各端在适配层实现页面跳转与功能唤醒的对应 API 及深链接注入,核心层只做解析、查表、拦截与按类型分发。
- 路由表可来自静态注册、编译期生成与动态下发,通过 merge 统一入口,便于与 02~06 所述方案无缝集成。
十一、核心类示范实现(伪代码)
便于各端实现时对齐行为,以下给出 RouteTableImpl 、InterceptorChain 、Router 的骨干逻辑。
csharp
类 RouteTableImpl 实现 IRouteTable:
_exact: Map<string, RouteItem> // 精确 path
_patterns: List<{ pattern: string, item: RouteItem }> // 带 :id 等
方法 register(item):
若 item.pattern 含动态段,追加到 _patterns;否则 _exact[item.path] = item
方法 lookup(path, params):
若 _exact[path] 存在,返回 (item, params)
遍历 _patterns,若匹配则返回 (item, mergedParams)
返回 null
方法 merge(items):
对 items 中每条,register(item) // 动态下发合并,后注册可覆盖
css
类 InterceptorChain:
_list: List<IRouteInterceptor>
方法 add(interceptor): _list.append(interceptor)
方法 process(context):
对 _list 按 order 排序后遍历:
若 !interceptor.process(context): interceptor.onInterrupt(context); 返回 false
返回 true
lua
类 Router 实现 IRouter:
依赖: IRouteTable table, InterceptorChain chain, IPlatformRouterAdapter adapter
方法 navigate(path, params, options):
result = table.lookup(path, params)
若 result == null: 返回 false
context = RouteContext(path, params, result, platformContext)
若 !chain.process(context): 返回 false
根据 options.mode 与 result.type 调用 adapter.openPage / replacePage / resolveService
返回 true
方法 handleOpenURL(url):
(path, params) = parseURL(url)
返回 navigate(path, params)
十二、各端统一调用示例(同一语义)
以下三端均使用相同语义:path、params、navigate 方式;仅底层由各端适配器实现。
12.1 iOS(Swift)业务侧
swift
// 注册(在模块初始化时)
Router.shared.register(path: "/page/detail") { params in
DetailViewController(itemId: params["id"] ?? "")
}
// 跳转(与 Android / Flutter 语义一致)
Router.shared.navigate(path: "/page/detail", params: ["id": "123"])
Router.shared.replace(path: "/page/list")
Router.shared.handleOpenURL(URL(string: "myapp://page/detail?id=123")!)
12.2 Android(Kotlin)业务侧
kotlin
// 注册
Router.register(RouteItem(path = "/page/detail", target = DetailActivity::class.java))
// 跳转
Router.navigate(context, "/page/detail", params = mapOf("id" to "123"))
Router.replace(context, "/page/list")
Router.handleOpenURL(context, Uri.parse("myapp://page/detail?id=123"))
12.3 Flutter(Dart)业务侧
dart
// 注册(在 go_router 或自定义 RouteTable 中)
routeTable.register('/page/detail', (params) => DetailPage(id: params['id']!));
// 跳转
Router.navigate(context, '/page/detail', params: {'id': '123'});
Router.replace(context, '/page/list');
Router.handleOpenURL(Uri.parse('myapp://page/detail?id=123'));
上述三端均通过同一 path 与 params 规范 接入深链接与动态下发的路由表,实现「一次配置、多端一致」的通用路由管理组件。HarmonyOS 、MacOS 、WinOS 、WebApp 、ReactNative 、WatchOS 的适配层实现同一套 navigate(path, params) / handleOpenURL 语义,仅底层调用各平台导航 API,见 08-软件体系与多平台路由对照。
参考文献
- 《01-软件平台路由规则设计-总纲》全文.
- 02~06 专题文档(URL Scheme、Universal Links、组件化路由、声明式路由、超级 App 路由体系).