美文网首页前端开发那些事儿jetpack
47. Navigation的使用和原理介绍

47. Navigation的使用和原理介绍

作者: 任振铭 | 来源:发表于2021-05-22 10:03 被阅读0次

    Google对Navigation的介绍

    今天,我们宣布推出Navigation组件,作为构建您的应用内界面的框架,重点是让单 Activity 应用成为首选架构。利用Navigation组件对 Fragment 的原生支持,您可以获得架构组件的所有好处(例如生命周期和 ViewModel),同时让此组件为您处理 FragmentTransaction 的复杂性。此外,Navigation组件还可以让您声明我们为您处理的转场。它可以自动构建正确的“向上”和“返回”行为,包含对深层链接的完整支持,并提供了帮助程序,用于将导航关联到合适的 UI 小部件,例如抽屉式导航栏和底部导航。

    引入

        implementation "androidx.navigation:navigation-fragment:2.3.2"
        implementation "androidx.navigation:navigation-ui:2.3.2"
    

    代码接入

    1.配置xml布局文件

    在主页MainActivity的XML文件中配置一个FragmentContainerView作为所有fragment的容器,将name设置为androidx.navigation.fragment.NavHostFragment,NavHostFragment会作为所有fragment的管理者而存在

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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"
        tools:context=".MainActivity">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/fragment_container_view_tag"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#00ff00"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toTopOf="@+id/bottom_navigation_view_id"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/navigation_main">
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    2.配置两个关键属性
    (1) app:defaultNavHost="true" (拦截系统Back键)

    拦截之后怎么处理呢?重写 Activity的 onSupportNavigateUp() 方法

    @Override
    public boolean onSupportNavigateUp() {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
        return NavHostFragment.findNavController(fragment).navigateUp();
    }
    
    (2).app:navGraph="@navigation/navigation_main"
    <?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_main.xml"
        //首次启动显示的默认fragment
        app:startDestination="@id/homeFragment">
        <fragment
            android:id="@+id/homeFragment"
            android:name="com.rzm.usingofnavigation.fragment.HomeFragment"
            android:label="homeFragment"
            tools:layout="@layout/fragment_home">
            //每一个action标识当前fragment可以跳转到的目标fragment
            <action
                android:id="@+id/action_feed"
                app:destination="@+id/feedFragment" />
            <action
                android:id="@+id/action_vide"
                app:destination="@+id/videoFragment" />
            <action
                android:id="@+id/action_mine"
                app:destination="@+id/mineFragment" />
        </fragment>
        <fragment
            android:id="@+id/feedFragment"
            android:name="com.rzm.usingofnavigation.fragment.FeedFragment"
            android:label="feedFragment"
            tools:layout="@layout/fragment_feed">
            <action
                android:id="@+id/action_home"
                app:destination="@+id/homeFragment" />
            <action
                android:id="@+id/action_vide"
                app:destination="@+id/videoFragment" />
            <action
                android:id="@+id/action_mine"
                app:destination="@+id/mineFragment" />
        </fragment>
    
        <fragment
            android:id="@+id/videoFragment"
            android:name="com.rzm.usingofnavigation.fragment.VideoFragment"
            android:label="videoFragment"
            tools:layout="@layout/fragment_video">
            <action
                android:id="@+id/action_home"
                app:destination="@id/homeFragment" />
            <action
                android:id="@+id/action_feed"
                app:destination="@id/feedFragment" />
            <action
                android:id="@+id/action_mine"
                app:destination="@id/mineFragment" />
        </fragment>
    
        <fragment
            android:id="@+id/mineFragment"
            android:name="com.rzm.usingofnavigation.fragment.MineFragment"
            android:label="mineFragment"
            tools:layout="@layout/fragment_mine">
            <action
                android:id="@+id/action_home"
                app:destination="@id/homeFragment" />
            <action
                android:id="@+id/action_feed"
                app:destination="@id/feedFragment" />
            <action
                android:id="@+id/action_vide"
                app:destination="@id/videoFragment" />
        </fragment>
    
    </navigation>
    
    3.跳转

    以HomeFragment到FeedFrament的跳转为例说明跳转代码

            view.findViewById(R.id.goFeed).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Navigation.findNavController(view).navigate(R.id.action_feed);
                }
            });
    

    原理

    Google设计Navigation的目的就是让我们可以像使用Activity一样方便的使用Fragment,只有使用方便的前提下,才能达到推进让单 Activity 应用成为首选架构的目标。我们知道Activity底层通过栈结构来管理,所以它可以轻松的实现跳转和回退。而Navigation的设计也是使用了这种方式,他的底层同样通过栈对fragment进行管理,实现多fragment的切换。重点在于navigation_main.xml中,在NavHostFragment创建的时候,这些内容就已经被解析存储起来了。

    相关文章

      网友评论

        本文标题:47. Navigation的使用和原理介绍

        本文链接:https://www.haomeiwen.com/subject/ytsnjltx.html