Jetpack-Navigation学习记录

用于页面跳转,功能很简单,下面看下用法吧

  1. 导入需要的库
	def nav_version = "2.3.2"
    // Java language implementation
    implementation "androidx.navigation:navigation-fragment:$nav_version"
    implementation "androidx.navigation:navigation-ui:$nav_version"
  1. 完成fragment的常规代码
    在这里插入图片描述
  2. 创建navigation目录,完成nav_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/FirstFragment">

    <fragment
        android:id="@+id/FirstFragment"
        android:name="com.example.jetpack_demo.fragment.Nav1Fragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment" />
    </fragment>
    <fragment
        android:id="@+id/SecondFragment"
        android:name="com.example.jetpack_demo.fragment.Nav2Fragment"
        android:label="@string/second_fragment_label"
        tools:layout="@layout/fragment_second">

        <action
            android:id="@+id/action_SecondFragment_to_FirstFragment"
            app:destination="@id/FirstFragment" />
    </fragment>
</navigation>

fragment 标签中注册Fragment ,action 标签中定义跳转动作,在页面上跳转时通过定义的action进行跳转

  1. 完成activity 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.NavigationSimpleActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/my_nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:defaultNavHost="true"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/nav_graph"
        />
   <!-- 底部导航-->
<!--    <com.google.android.material.bottomnavigation.BottomNavigationView-->
<!--        android:id="@+id/nav_view"-->
<!--        android:layout_width="match_parent"-->
<!--        android:layout_height="50dp"-->
<!--        app:itemTextColor="#ff0000"-->
<!--        app:menu="@menu/menu"/>-->

</LinearLayout>

app:defaultNavHost="true" 的作用:拦截系统back键 app:navGraph="@navigation/nav_graph" 的作用:设置跳转路由

  1. 完成activity.java的内容
public class NavigationSimpleActivity extends AppCompatActivity {

    BottomNavigationView bottomNavigationView;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_navigation_simple);
//        底部导航功能
//        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
//        bottomNavigationView = findViewById(R.id.nav_view);
//        NavController controller = navHostFragment.getNavController();
//        NavigationUI.setupWithNavController(bottomNavigationView,controller);
    }

    @Override
    public boolean onSupportNavigateUp() {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
        return NavHostFragment.findNavController(fragment).navigateUp();
    }
}
  1. 完善Fragment中的按钮跳转功能
public class Nav1Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_first,container,false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        view.findViewById(R.id.button_first).setOnClickListener(v -> {
            //页面跳转
            Navigation.findNavController(view).navigate(R.id.action_FirstFragment_to_SecondFragment);
        });
    }
}

运行项目,页面就可以实现页面跳转了。

as中直接通过basic Activity创建的页面和上述功能差不多
如果想创建一个带底部导航的,可以用bottom navigation activity 创建
在这里插入图片描述

navigation 原理

上课老师总结的,贴上来,方便以后复习

JetPack技术

Navigation基本使用

请参考上课代码

Navigation原理

初始化过程 NavHostFragment生命周期方法

  • 1.NavHostFragment的创建
    NavHostFragment.create方法
    (1)初始化Bundle,并且将graphResId,startDestinationArgs存储在Bundle中。
    (2)new NavHostFragment()返回NavHostFragment实例。

  • 2.XML文件的解析:主要是解析布局文件的两个属性。defaultNavHost和navGraph,并且初始化全局变量
    NavHostFragment.onInflate方法 当Fragment以XML的方式静态加载时,最先会调用onInflate的方法
    (调用时机:Fragment所关联的Activity在执行setContentView时)

  • 3.onCreateNavController方法中

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

mNavController.getNavigatorProvider().addNavigator(createFragmentNavigator());
- 1.其中mNavigatorProvider是NavController中的全局变量,内部通过HashMap键值对的形式保存Navigator类。
- 2.createFragmentNavigator方法,构建了FragmentNavigator对象,其中抽象类Navigator还有个重要的实现类ActivityNavigator和NavGraphNavigator。
这个两个类的对象在NavController的构造方法中被添加。

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

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

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

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

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

- .setGraph()方法

构建NavGraph
在构建NavController的时候,我们还调用了NavController.setGraph(graphId)方法,
该方法主要是构建NavGraph。
(1)调用getNavInflater方法创建NavInflater对象,用于解析navigation xml
- 4. NavInflater.inflate方法
根据传入的XML资源id构建NavGraph,NavGraph组成Fragment路由的导航地图,而NavDestination代表了导航的每一个目的地。在解析完NavDestination后,需要要求NavDestination为NavGraph,即NavGraph是NavDestination的子类。而且在NavGraph内部存储了NavDestination信息。

- 5.上面的inflate方法内部会继续调用inflate方法。 

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

- 6.

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

- 7.onGraphCreated方法

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

  • 4.NavHostFragment.onCreateView方法
    该NavHostFragment的视图就只有一个FragmentContainerView extends FrameLayout
    containerView.setId(getContainerId());//这行主要用于以代码方式添加fragment
  • 5.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)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执行。

思维导图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值