ArkUI-X/arkui_for_android路由导航:页面跳转与参数传递
概述
ArkUI-X作为华为推出的跨平台UI框架,在Android平台的适配层提供了强大的路由导航能力。本文将深入解析arkui_for_android项目的路由导航机制,重点介绍页面跳转的实现原理和参数传递的最佳实践。
路由导航架构设计
核心组件关系
路由配置解析
ArkUI-X的路由配置通过BundleInfo中的routerArray实现,每个路由项包含:
| 字段 | 类型 | 描述 |
|---|---|---|
| name | string | 路由名称标识符 |
| bundleName | string | 所属Bundle名称 |
| moduleName | string | 模块名称 |
| pageSourceFile | string | 页面源文件路径 |
| data | string | 路由参数数据 |
页面跳转实现机制
1. 路由初始化
void NavigationRoute::InitRouteMap()
{
auto applicationContext = AbilityRuntime::Platform::ApplicationContext::GetInstance();
if (applicationContext == nullptr) {
TAG_LOGE(AceLogTag::ACE_NAVIGATION, "applicationContext is nullptr");
return;
}
auto bundleContainer = applicationContext->GetBundleContainer();
if (!bundleContainer) {
TAG_LOGE(AceLogTag::ACE_NAVIGATION, "get bundle container failed");
return;
}
AppExecFwk::BundleInfo bundleInfo;
if (bundleContainer->GetBundleInfoForSelf(
static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) +
static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ROUTER_MAP),
bundleInfo) != 0) {
TAG_LOGE(AceLogTag::ACE_NAVIGATION, "get bundle info failed");
return;
}
allRouteItems_ = bundleInfo.routerArray;
moduleInfos_ = bundleInfo.hapModuleInfos;
}
2. 页面加载流程
参数传递机制
1. 路由参数配置
路由参数通过RouterItem的data字段进行传递:
bool NavigationRoute::GetRouteItem(const std::string& name, NG::RouteItem& info)
{
AppExecFwk::RouterItem routeItem;
if (!GetRouteItemFromBundle(name, routeItem)) {
TAG_LOGE(AceLogTag::ACE_NAVIGATION, "get route info %{public}s failed", name.c_str());
return false;
}
info.name = routeItem.name;
info.bundleName = routeItem.bundleName;
info.moduleName = routeItem.moduleName;
info.pageSourceFile = routeItem.pageSourceFile;
info.data = routeItem.data; // 参数数据传递
return true;
}
2. 运行时参数传递
在AceContainerSG中,RunPage方法支持动态参数传递:
static bool RunPage(int32_t instanceId, int32_t pageId, const std::string& content,
const std::string& params, bool isNamedRouter = false);
参数说明:
instanceId: 容器实例IDpageId: 页面IDcontent: 页面内容params: 参数字符串(JSON格式)isNamedRouter: 是否使用命名路由
命名路由与普通路由
命名路由(Named Router)
// 使用命名路由跳转
AceContainerSG::RunPage(instanceId, pageId, content, params, true);
// 对应的路由配置
{
"name": "userDetail",
"bundleName": "com.example.app",
"moduleName": "entry",
"pageSourceFile": "pages/UserDetailPage.ets",
"data": "{\"defaultUserId\":1001}"
}
普通路由
// 使用普通路由跳转
AceContainerSG::RunPage(instanceId, pageId, content, params, false);
路由查找与验证
1. 路由存在性检查
bool NavigationRoute::IsNavigationItemExits(const std::string& name)
{
if (HasLoaded(name)) {
return true; // 已加载的路由
}
AppExecFwk::RouterItem item;
if (GetRouteItemFromBundle(name, item)) {
return true; // 配置文件中存在的路由
}
return false; // 路由不存在
}
2. 路由项查找算法
bool NavigationRoute::GetRouteItemFromBundle(const std::string& name, AppExecFwk::RouterItem& routeItem)
{
for (auto moduleIter = allRouteItems_.begin(); moduleIter != allRouteItems_.end(); moduleIter++) {
if (moduleIter->name == name) {
routeItem = *moduleIter;
return true;
}
}
TAG_LOGE(AceLogTag::ACE_NAVIGATION, "can't find name in config file: %{public}s", name.c_str());
return false;
}
跨模块路由加载
ArkUI-X支持跨HAP模块的路由加载:
int32_t NavigationRoute::LoadPageFromHapModule(const std::string& name)
{
int32_t res = -1;
if (!callback_) {
return res;
}
for (auto hapIter = moduleInfos_.begin(); hapIter != moduleInfos_.end(); hapIter++) {
auto routerInfo = hapIter->routerArray;
for (auto routerIter = routerInfo.begin(); routerIter != routerInfo.end(); routerIter++) {
if (routerIter->name != name) {
continue;
}
res = callback_(routerIter->bundleName, routerIter->moduleName,
routerIter->ohmurl, false);
TAG_LOGD(AceLogTag::ACE_NAVIGATION,
"load current destination name: %{public}s, ohmurl: %{public}s",
name.c_str(), routerIter->ohmurl.c_str());
if (res == 0) {
return 0;
}
break;
}
}
return res;
}
错误处理与日志
错误码定义
| 错误码 | 描述 | 处理建议 |
|---|---|---|
| 0 | 成功 | 正常继续 |
| -1 | 回调函数未设置 | 检查callback_初始化 |
| ERROR_CODE_BUILDER_FUNCTION_NOT_REGISTERED | 路由功能未注册 | 确认路由配置正确 |
日志输出示例
TAG_LOGI(AceLogTag::ACE_NAVIGATION,
"load navdestination %{public}s, ohmurl: %{public}s",
item.bundleName.c_str(), item.moduleName.c_str());
最佳实践
1. 路由配置规范
// router.config.json
{
"routes": [
{
"name": "home",
"bundleName": "com.example.app",
"moduleName": "entry",
"pageSourceFile": "pages/HomePage.ets",
"data": "{}"
},
{
"name": "userProfile",
"bundleName": "com.example.app",
"moduleName": "entry",
"pageSourceFile": "pages/UserProfilePage.ets",
"data": "{\"requireAuth\":true}"
}
]
}
2. 参数传递示例
// 构造参数JSON
std::string params = R"({
"userId": 12345,
"userName": "张三",
"fromPage": "home"
})";
// 执行页面跳转
AceContainerSG::RunPage(instanceId, GeneratePageId(), "", params, true);
3. 错误处理策略
int32_t result = navigationRoute->LoadPage("targetPage");
if (result != 0) {
// 处理路由加载失败
HandleNavigationError(result, "targetPage");
}
性能优化建议
- 路由预加载: 对常用路由进行预加载,减少首次跳转延迟
- 路由缓存: 实现路由信息缓存机制,避免重复解析配置
- 懒加载: 对不常用的路由模块实现按需加载
- 内存管理: 及时释放不再使用的路由资源
总结
ArkUI-X/arkui_for_android的路由导航系统提供了完整的页面跳转和参数传递解决方案。通过NavigationRoute和AceContainerSG的协同工作,实现了高效的路由管理、参数传递和错误处理机制。开发者可以根据业务需求灵活选择命名路由或普通路由,并通过规范的参数传递机制实现页面间的数据交互。
掌握这些路由导航的核心概念和最佳实践,将帮助开发者构建更加流畅和可维护的跨平台应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



