移动 前端 Python Android JavaAndroid-JetpackJetpackPack 知识

Jetpack Navigation 原理浅析

2021-01-23  本文已影响0人  zcwfeng

Navigation 的 源码分析

2021-01-23 12.37.54.png

NavHostFragment 的生命周期方法,断点流程

onInflate  ---->onAttach--->onCreate--->onCreateNavController
--->createFragmentNavigator--->onCreateView--->onViewCreated
--->onPrimaryNavigationFragmentChanged

NavHostFragment#create API 入口

1. onInflate

解析XML,主要解析布局文件两个属性

graphResId 设置,保存KEY_GRAPH_ID

startDestinationArgs,保存目标参数,KEY_START_DESTINATION_ARGS

最终创建实例 new NavHostFragment,并讲inflate出来属性绑定

2. onCreate

导航初始化 
无论是XML实现还是代码实现,都会执行Fragment的onCreate方法.
NavController在这里被创建,并且NavHostFragment中有一个NavController对象。

(1)初始化NavController,NavController为导航的控制类,核心类。
        mNavController = new NavHostController(context);

(2)if (savedInstanceState != null) {开始恢复状态}

(3)if (mGraphId != 0) {设置导航图信息}

初始化new NavHostController

onCreateNavController

在实现导航的时候,我们需要根据navigation配置文件生成NavGraph类,然后在根据每个不同的action id,找到对应的NavDestination就可以实现页面导航跳转了。

mNavController.getNavigatorProvider().addNavigator(createFragmentNavigator());

构建了FragmentNavigator对象,其中抽象类Navigator还有个重要的实现类ActivityNavigator和NavGraphNavigator。
这个两个类的对象在NavController的构造方法中被添加。

其中Navigator类的作用是:能够实例化对应的NavDestination,并且能够实现导航功能,拥有自己的回退栈。

.setGraph()

构建NavGraph
在构建NavController的时候,我们还调用了NavController.setGraph(graphId)方法,
该方法主要是构建NavGraph。

调用getNavInflater方法创建NavInflater对象,用于解析navigation xml

NavInflater.inflate方法

根据传入的XML资源id构建NavGraph,NavGraph组成Fragment路由的导航地图,而NavDestination代表了导航的每一个目的地。在解析完NavDestination后,需要要求NavDestination为NavGraph,即NavGraph是NavDestination的子类。而且在NavGraph内部存储了NavDestination信息。

(1)getNavigator方法获取都Navigator实例,该实例在构建NavController是被添加进去,这里获取的是FragmentNavigator对象。
(2)createDestination方法,会调用FragmentNavigator的createDestination构建Destination对象。
(3)onInflate方法,解析destination XML
(4)while循环内部通过递归构建导航图。

通过NavInflater类之后,解析了XML文件构建整个Graph之后。,
下面回到setGraph方法,在解析完XML后会,
回到NavHostFragment.setGraph方法。
(1)popBackStackInternal方法将回退栈中的信息全部出栈。
(2)调用onGraphCreated主要是显示一个导航Fragment视图。

onGraphCreated方法 ---- NavController#navigate
(1)恢复之前的导航状态
(2)调用navigate方法,显示第一个Fragment。即在Navigation文件里,属性app:startDestination的Fragment。所以最终都会走到navigate导航方法。

3. onCreateView

NavHostFragment.onCreateView方法
该NavHostFragment的视图就只有一个FragmentContainerView extends FrameLayout
containerView.setId(getContainerId());//这行主要用于以代码方式添加fragment

4. onViewCreated

NavHostFragment.onViewCreated
//把mNavController记录在view的tag中
Navigation.setViewNavController(view, mNavController);

获取NavController

1.获取NavController
NavHostFragment.findNavController(fragment)
2.findNavController方法 该方法没什么实质性的代码,只要是调用了findViewNavController方法。
3.findViewNavController方法 通过view.tag查找NavController。内部调用了getViewNavController方法。
4.getViewNavController方法 通过获取view的Tag,获取NavController对象,这里的tag ID和setViewNavController都是nav_controller_view_tag。

导航

1.在构建和获取到NavController对象以及NavGraph之后。,
下面是使用它来实现真正的导航了。下面从navigate开始分析。在navigate方法内部会查询到NavDestination,然后根据不同的Navigator实现页面导航。
navigate 方法
(1)如果回退栈为null返回NavGraph,不为null返回回退栈中的最后一项。
NavDestination currentNode = mBackStack.isEmpty()
? mGraph
: mBackStack.getLast().getDestination();
(2)根据id,获取对应的NavAction。然后在通过NavAction获取目的地id。
final NavAction navAction = currentNode.getAction(resId);
destId = navAction.getDestinationId();
(4)利用目的地ID属性,通过findDestination方法,找到准备导航的目的地。
NavDestination node = findDestination(destId);
(5)开始导航
1.navigate(node, combinedArgs, navOptions, navigatorExtras);
2.NavDestination newDest = navigator.navigate(node, finalArgs,
navOptions, navigatorExtras);

2.FragmentNavigator的实现
通过以上的分析,又来到了Navigator 的子类FragmentNavigator类。下面来看看FragmentNavigator.navigate的方法。
(1)调用instantiateFragment,通过反射机制构建Fragment实例
(2)处理进出场等动画逻辑
(3)最终调用FragmentManager来处理导航逻辑。
**ActivityNavigator最终也是调用了startActivity方法

  1. 综上
nav2021_2.jpeg

(1)NavHostFragment 作为导航载体,在Activity的layout文件里被引用(或者在代码中动态),并且持有导航控制类NavController引用。
(2)NavController 将导航任务委托给Navigator类,Navigator类有两个重要的子类FragmentNavigator和ActivityNavigator子类。NavController类持有NavInflater类引用。
(3)NavInflater 负责解析Navgation文件,负责构建NavGraph导航图。
(4)NavDestination 存有各个目的地信息,在FragmentNavigator和ActivityNavigator内部分别对应一个Destination类,该类继承NavDestination。
(5)在页面导航时,fragment的操作还是交由FragmentManager在操作,activity交由startActivity执行。

上一篇下一篇

猜你喜欢

热点阅读