当前位置: 首页 > news >正文

Android Navigation 原理解析

1. nav_graph.xml 如何生成路由表 NavGraph

解析流程与原理

关键技术点:
  1. XML 解析

    • 使用 XmlResourceParser 解析 XML 文件

    • 遍历所有节点(<fragment><activity><navigation>等)

  2. Destination 创建

    • 根据标签名获取对应的 Navigator

    • 调用 Navigator.createDestination() 创建具体目标

    • 解析节点属性(id、label、arguments 等)

  3. NavGraph 构建

    • 维护节点树结构

    • 处理嵌套导航图(递归解析)

    • 建立 action 连接关系

核心源码解析:
// NavInflater.java
public NavGraph inflate(@XmlRes int graphResId) {// 获取XML解析器XmlResourceParser parser = mContext.getResources().getXml(graphResId);// 创建空导航图NavGraph graph = new NavGraph(this);while (parser.next() != XmlPullParser.END_DOCUMENT) {if (parser.getEventType() != XmlPullParser.START_TAG) continue;String tagName = parser.getName();// 获取对应标签的NavigatorNavigator navigator = mNavigatorProvider.getNavigator(tagName);// 创建DestinationNavDestination destination = navigator.createDestination();// 解析属性destination.onInflate(mContext, parser);if (destination instanceof NavGraph) {// 递归解析嵌套图inflateChildren(parser, (NavGraph)destination);}// 添加到导航图graph.addDestination(destination);}return graph;
}

2. startDestinationId 启动页加载机制

启动流程原理

关键实现细节:
  1. 启动时机

    • NavHostFragment 的 onCreate() 方法中初始化

    • 首次设置导航图时触发启动流程

  2. 导航执行

    • 通过 FragmentNavigator.navigate() 执行

    • 使用反射创建 Fragment 实例:

      final Fragment fragment = mFragmentManager.getFragmentFactory().instantiate(mContext.getClassLoader(), dest.getClassName());
  3. 事务处理

    • 使用 FragmentTransaction.replace() 替换容器内容

    • 提交事务后立即执行(commitNow()

源码关键路径:
// NavController.java
public void setGraph(@NavGraphRes int graphResId) {mGraph = mNavInflater.inflate(graphResId);onGraphCreated(); // 触发首次导航
}private void onGraphCreated() {if (mBackStack.isEmpty()) {// 导航到起始目标navigate(mGraph, mGraph.getStartDestination(), null, null);}
}// FragmentNavigator.java
public NavDestination navigate(...) {// 创建Fragment实例final Fragment frag = instantiateFragment(context, className, args);final FragmentTransaction ft = mFragmentManager.beginTransaction();// 执行替换操作ft.replace(mContainerId, frag);ft.commit();return destination;
}

3. Fragment 页面切换为何执行 onDestroyView

根本原因分析

设计原理:
  1. 默认行为

    • FragmentNavigator 使用 replace() 而非 show/hide

    • 替换操作会销毁上一个 Fragment 的视图

  2. 生命周期对比

    导航方式前Fragment生命周期新Fragment生命周期
    replace()onPause→onDestroyViewonCreateView→onResume
    show/hide()onPauseonResume
  3. 官方设计考量

    • 确保状态一致性

    • 避免视图叠加导致的潜在问题

    • 简化内存管理

性能影响:
  • 优点:严格的内存管理,避免泄露

  • 缺点

    • 视图重建开销(特别是复杂UI)

    • 状态保存/恢复复杂化

    • 影响转场动画流畅性

4. singleTop 失效问题深度解析

问题现象与原因

源码级分析:
// FragmentNavigator.java
public NavDestination navigate(...) {// 无单例模式检查逻辑!// 始终创建新实例final Fragment frag = instantiateFragment(...);// 始终执行replaceft.replace(mContainerId, frag);
}
与 Activity singleTop 对比:
特性Activity singleTopFragment "singleTop"
栈顶复用调用 onNewIntent()始终重建
生命周期无销毁/重建完整生命周期
实现机制框架原生支持Navigation 未实现
官方未修复原因:
  1. 架构限制

    • Fragment 无内置任务栈管理

    • 缺乏类似 onNewIntent() 的回调机制

  2. 状态一致性

    • 确保每次导航都传递新参数

    • 避免状态污染

  3. 设计选择

    • 优先保证导航行为一致性

    • 牺牲特殊场景优化

相关文章:

  • 厦门网站建设 软件园百度问答平台入口
  • 德钦网站建设网站优化公司怎么选
  • 网站域名注册人查询南宁百度快速排名优化
  • 重庆公司注册网站做游戏推广一个月能拿多少钱
  • 互联网时代 网站建设上海网站建设
  • 做公司网站哪家好国外黄冈网站推广软件
  • C++字符串的行输入
  • 华为服务器的选型指南
  • AI + 化学实验:从“黑匣子”到“显微镜”,人工智能如何让化学研究更聪明?
  • TouchDIVER Pro触觉手套:虚拟现实中的多模态交互新选择
  • day41/60
  • OSS大数据分析集成:MaxCompute直读OSS外部表优化查询性能(减少数据迁移的ETL成本)
  • Springboot项目中使用手机号短信验证码注册登录实现
  • Starrocks 低基数全局字典优化
  • 【stm32】标准库学习——USART串口
  • 攻防世界-MISC-MeowMeowMeow
  • C++面试题(46)------滑动窗口的最大值
  • vue 路由学习
  • Python核心库Pandas详解:数据处理与分析利器
  • 【最新实时目标检测YOLOv13添加PyQt可视化界面】
  • 旁挂式集中转发AC基础配置
  • 对手机屏中断路和短路的单元进行切割或熔接,实现液晶线路激光修复原理
  • 《贵州棒垒球》有什么国家级比赛·棒球1号位
  • Qt面试题汇总
  • 集成 Odoo、n8n 与 Dify,实现智能业务流程自动化
  • 通过环境变量管理多版本JDK8、11、17并安装idea编译器