特殊的Destination,将app:navGraph="@navigation/nav_graph解析封装成NavGraph对象,里面包含nav_graph.xml中的所有信息。 首先我们知道NavGraph中是包含nav_graph所有节点的内容。 (this) this=NavGraphNavigator: 跟进: public NavGraph createDestination() { return new NavGraph (this); } public NavGraph(@NonNull Navigator<? 同时在递归中把所有NavDestination节点addDestination()到NavGraph中: NavGraph: SparseArrayCompat<NavDestination> mNodes
先在布局文件中去掉app:navGraph="@navigation/mobile_navigation",然后来到activity,编写如下代码, //NavigationActivity.java navGraph = initNavGraph(provider, fragmentNavigator); //设置导航图 navController.setGraph(navGraph initNavGraph(NavigatorProvider provider, FixFragmentNavigator fragmentNavigator) { NavGraph navGraph (destination1); //省略 navGraph.addDestination(destination2); //省略 navGraph.addDestination (destination3); navGraph.setStartDestination(R.id.navigation_home); return navGraph; } 具体流程都写在代码注释里了
layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph 方式一: google的demo中是在MainActivity中创建一个main_navGraph,其中包含了不同子moduel的navGraph ,如下: <? app:graph="@navigation/navi_center"/> </navigation> navi_home 、navi_collection 、navi_center是子moduel中的navGraph 方式二: 因为app module本身是需要依赖各个子moduel的,我们可以在navGraph直接使用子moduel中的Fragment,主页面只需加入各个module的主Fragment就行了:
由此可见,导航资源文件nav_graph会被解析成一个NavGraph对象,看下NavGraph public class NavGraph extends NavDestination implements 继承了NavDestination,NavDestination其实就是nav_graph.xml中navigation下的一个个节点,也就是一个个页面,NavGraph内部有个集合mNodes,用来保存一组 (destination instanceof NavGraph)) { throw new IllegalArgumentException("Root element <" + rootElement + ">" + " did not inflate into a NavGraph"); } return 那么我们是不能在布局文件中通过app:navGraph属性指定自定义的导航资源文件了,只能在布局文件中去掉app:navGraph这个属性,然后在添加FixFragmentNavigator的同时,通过代码将导航资源文件设置进去
new TypeReference<HashMap<String, Destination>>() { }.getType()); /** * 创建NavGraph 它是解析mobile_navigation.xml文件后,存储所有节点的Destination * 我们解析的Destination节点,最终都要存入NavGraph中 NavGraph navGraph = new NavGraph(navigator); //创建我们自定义的FragmentNavigator HiFragmentNavigator (destination.id); } } // 视图navGraph和controller 相关联 controller.setGraph (navGraph); } private static String parseFile(Context context, String fileName) {
--app:navGraph="@navigation/mobile_navigation"设置Fragment对应的导航图--> <fragment android:id="@+id/ match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph initNavGraph(NavigatorProvider provider, FixFragmentNavigator fragmentNavigator) { NavGraph navGraph = new NavGraph(new NavGraphNavigator(provider)); //用自定义的导航器来创建目的地 FragmentNavigator.Destination (destination3); navGraph.setStartDestination(destination1.getId()); return navGraph
FragmentContainerView是一个特殊的Fragment,只能添加Fragment, app:navGraph:这里需要指定前面在res文件夹下创建的navigation文件 app:defaultNavHost NavOptions.Builder() .setPopUpTo(R.id.fragmentOne, true) .build() Navigation动态加载 除了在xml中设置navGraph ,有很多场景下,我们会根据业务场景动态设置一些navGraph,或者某些navGraph是需要动态获取一些参数之后才去初始化的,这时候,就可以使用Navigation的动态加载方案。 首先,需要在Fragment容器中,去掉navGraph的引用,然后在Activity中,动态指定要引用的navGraph,代码如下所示。 R.id.loginFragment navHostFragment.navController.graph = navigation 实际上和动态Inflate布局再添加布局到容器的场景非常类似,Navigation动态加载也是将navGraph
popBackStack()回退上一级时有什么区别,该如何正确使用 跳转时 有时用的是Action的ID,有时用的是Fragment的ID 他俩到底在什么场景下,区分该将哪个传入方法作为参数 使用和核心方法 1.创建NavGraph app:layout_constraintBottom_toBottomOf="parent" app:defaultNavHost="true" app:navGraph ="@navigation/nav_graph" /> 以上3个配置比较重要: app:defaultNavHost="true" app:navGraph="@navigation/nav_graph 拦截返回键的点击事件,这样Fragment就可以想Activity一样,具有回退,返回事件 配置路由XML文件,然后加载进NavHostFragment中 app:navGraph属性,对应的就是NavGraph 代码实现路由跳转和方法解析 3.1 核心方法 Acitivty#findNavController() 传入navGraph id Fragment#findNavController() 直接调用
image.png FragmentContainerView是一个特殊的Fragment,只能添加Fragment, app:navGraph:这里需要指定前面在res文件夹下创建的navigation NavOptions.Builder() .setPopUpTo(R.id.fragmentOne, true) .build() Navigation动态加载 除了在xml中设置navGraph ,有很多场景下,我们会根据业务场景动态设置一些navGraph,或者某些navGraph是需要动态获取一些参数之后才去初始化的,这时候,就可以使用Navigation的动态加载方案。 首先,需要在Fragment容器中,去掉navGraph的引用,然后在Activity中,动态指定要引用的navGraph,代码如下所示。 R.id.loginFragment navHostFragment.navController.graph = navigation 实际上和动态Inflate布局再添加布局到容器的场景非常类似,Navigation动态加载也是将navGraph
Fragment,这个Fragment的name是androidx.navigation.fragment.NavHostFragment,这是一个添加到布局中的特殊部件,NavHostFragment通过navGraph :layout_height="match_parent" app:defaultNavHost="true" app:navGraph 接下来我们看到为NavController设置了setGraph(),也就是我们xml里面定义的navGraph,导航布局里面的Fragment及action跳转等信息。 3.2 NavController /** * Sets the {@link NavGraph navigation graph} to the specified graph. = new ArrayDeque<>(); NavGraph parent = newDest.getParent(); while (parent !
layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph
Navigation是一种导航的概念,即把Activity和fragment当成一个个的目的地Destination,各目的地形成一张导航图NavGraph,由导航控制器NavController来统一调度跳转 -- fragment作为页面容器,navGraph指定了导航图的结构 --> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost="true" app:navGraph
Fragment,这个Fragment的name是androidx.navigation.fragment.NavHostFragment,这是一个添加到布局中的特殊部件,NavHostFragment通过navGraph :layout_height="match_parent" app:defaultNavHost="true" app:navGraph 接下来我们看到为NavController设置了setGraph(),也就是我们xml里面定义的navGraph,导航布局里面的Fragment及action跳转等信息。 3.2 NavController /** * Sets the {@link NavGraph navigation graph} to the specified graph. = new ArrayDeque<>(); NavGraph parent = newDest.getParent(); while (parent !
Fragment,这个Fragment的name是androidx.navigation.fragment.NavHostFragment,这是一个添加到布局中的特殊部件,NavHostFragment通过navGraph :layout_height="match_parent" app:defaultNavHost="true" app:navGraph 接下来我们看到为NavController设置了setGraph(),也就是我们xml里面定义的navGraph,导航布局里面的Fragment及action跳转等信息。 3.2 NavController /** * Sets the {@link NavGraph navigation graph} to the specified graph. = new ArrayDeque<>(); NavGraph parent = newDest.getParent(); while (parent !
Component 的三个核心角色Navigation Component 里最常见的三个概念是:NavHost:页面容器,用来承载不同目的地NavController:导航控制器,负责执行跳转和返回NavGraph :导航图,描述页面之间的关系可以简单理解成:NavGraph 负责定义路线NavHost 负责显示页面NavController 负责执行跳转这三个角色分清之后,Navigation Component layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph ="@navigation/nav_graph" />几个属性需要注意:android:name 指定这里使用的是 NavHostFragmentapp:navGraph 绑定刚才创建的导航图app:defaultNavHost
match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph 布局 在 Activity 的布局文件中 , 添加如下代码 , 不建议在 Design 界面直接拖动 NavHostFragment , 生成的代码报错 , 直接拷贝下面的代码即可 ; 将 app:navGraph android:layout_width="match_parent" android:layout_height="match_parent" app:navGraph android:layout_width="match_parent" android:layout_height="match_parent" app:navGraph
layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:navGraph androidx.navigation.fragment.NavHostFragment ; 查看 app:defaultNavHost=“true” 属性是否设置 ; 查看 NavigationGraph 的设置 app:navGraph
my_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:navGraph my_nav_host_fragment" android:name="com.demo.navigationcomponent.TabNavHostFragment" app:navGraph
match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph 使用 android:name 指定 Fragment 的类型为 NavHostFragment,使用 app:navGraph 指定 Navigation 文件。
它会暴露出一连串小项目里根本不会遇到的问题——ViewModel 范围怎么定、进程被杀后 BackStack 怎么还原、不同模块之间怎么互相导航、外部 deep link 进来到底落在哪个 NavGraph 这是最简单的,但当 Route 数量多了,这个模块会变得很臃肿,而且任何 Route 改动都会触发全量编译 • 每个 feature 提供自己的 NavGraph 扩展函数:feature_detail Activity 之后选项变多了: • 绑 Activity:所有页面共享,跟全局单例几乎没区别 • 绑 NavBackStackEntry:跟着具体页面走,离开页面就销毁 • 绑某个 Nested NavGraph SingletonComponent:跨页面长期存在 大部分场景用 NavBackStackEntry 范围就够了,但下单流程、表单分步、引导流这种"几个页面共享一份草稿状态"的场景,需要 Nested NavGraph