Navigation深入淺出,到出神入化活尊,再到實(shí)戰(zhàn)改造

思考幾個問題:

  1. 可以在代碼中用Bundle傳遞參數(shù)隶校,為什么要在XML去配置
  2. XML中的參數(shù)標(biāo)簽,只能設(shè)置和讀取蛹锰,無法在XML中跳轉(zhuǎn)是附帶傳過去深胳,如B頁面要求傳入name:String,于是在<Argment>標(biāo)簽中配置,但A去跳轉(zhuǎn)時铜犬,無法在XML中傳入舞终,只能在代碼中定義參數(shù)名稱和值,那么XML的參數(shù)還有何意義癣猾?有什么實(shí)用的場景敛劝?
  3. navigationUp和popBackStack()回退上一級時有什么區(qū)別,該如何正確使用
  4. 跳轉(zhuǎn)時 有時用的是Action的ID纷宇,有時用的是Fragment的ID 他倆到底在什么場景下夸盟,區(qū)分該將哪個傳入方法作為參數(shù)

使用和核心方法

1.創(chuàng)建NavGraph

圖片.png
<?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/home_fragment">
    <fragment
        android:id="@+id/home_fragment"
        android:name="org.devio.proj.navigationdemo.HomeFragment"
        android:label="@string/hello_blank_fragment"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/home_to_other"
            app:destination="@id/other_fragment"
            app:enterAnim="@anim/fade_in"
            app:exitAnim="@anim/fade_out" />
    </fragment>

    <fragment
        android:id="@+id/other_fragment"
        android:name="org.devio.proj.navigationdemo.OtherFragment"
        android:label="@string/hello_blank_fragment"
        tools:layout="@layout/fragment_other">

        <action
            android:id="@+id/other_to_deeplink"
            app:destination="@id/nav_graph_to" />
        
        <argument
            android:name="home_arg_name"
            android:defaultValue="defName"
            app:argType="string"
            app:nullable="true" />

        <argument
            android:name="home_arg_age"
            android:defaultValue="99"
            app:argType="integer" />
        <argument
            android:name="home_arg_mode"
            app:argType="org.devio.proj.navigationdemo.Model" />
        <!--        <deepLink-->
        <!--        android:id="@+id/deepLink"-->
        <!--        app:uri="www.baidu.com" />-->
        <!--        android:autoVerify="false"
                    app:action="ACTION_SEND"
                    app:mimeType="text/html"-->
    </fragment>

    <navigation
        android:id="@+id/nav_graph_to"
        android:label="SecondHome"
        app:startDestination="@id/deep_link_fragment">
        <fragment
            android:id="@+id/deep_link_fragment"
            android:name="org.devio.proj.navigationdemo.DeeplinkFragment"
            android:label="@string/hello_blank_fragment"
            tools:layout="@layout/fragment_deeplink">

            <action
                android:id="@+id/deeplink_to_home"
                app:popUpTo="@id/home_fragment" />
        </fragment>
        <fragment
            android:id="@+id/settingFragment"
            android:name="org.devio.proj.navigationdemo.SettingFragment"
            android:label="fragment_setting"
            tools:layout="@layout/fragment_setting" />
    </navigation>
</navigation>

==navigation== :視圖導(dǎo)航的根部標(biāo)簽, ==app:startDestination="@id/home_fragment"== 指定以哪個頁面為首頁像捶。<navigation> 標(biāo)簽下包含3中子標(biāo)簽上陕。:

<activity></activity>  支持Activity 跳轉(zhuǎn)
<dialog></dialog>      支持 dialogFragment 跳轉(zhuǎn)
<fragment></fragment>  支持fragment 跳轉(zhuǎn)

出以上三種跳轉(zhuǎn)類型外,==</navigation>== 標(biāo)簽下還支持嵌套操作作岖。

 <navigation>
        <navigation>
            
        </navigation>
        
         <include  >// 嵌套另一個nav_graph ,注意:
         這個布局只能是<navigation>為根節(jié)點(diǎn)的布局

        </include>
    </navigation>

以Fragment為例唆垃,創(chuàng)建3個Fragment實(shí)例五芝,分別為HomeFragment痘儡,OtherFragment,DeeplinkFragment枢步。


<?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/home_fragment">
    <fragment
        android:id="@+id/home_fragment"
        android:name="org.devio.proj.navigationdemo.HomeFragment"
        android:label="@string/hello_blank_fragment"
        tools:layout="@layout/fragment_home">
    </fragment>

    <fragment
        android:id="@+id/other_fragment"
        android:name="org.devio.proj.navigationdemo.OtherFragment"
        android:label="@string/hello_blank_fragment"
        tools:layout="@layout/fragment_other">
    </fragment>

    <navigation
        android:id="@+id/nav_graph_to"
        android:label="SecondHome"
        app:startDestination="@id/deep_link_fragment">
        <fragment
            android:id="@+id/deep_link_fragment"
            android:name="org.devio.proj.navigationdemo.DeeplinkFragment"
            android:label="@string/hello_blank_fragment"
            tools:layout="@layout/fragment_deeplink">

            <action
                android:id="@+id/deeplink_to_home"
                app:popUpTo="@id/home_fragment" />
        </fragment>
        <fragment
            android:id="@+id/settingFragment"
            android:name="org.devio.proj.navigationdemo.SettingFragment"
            android:label="fragment_setting"
            tools:layout="@layout/fragment_setting" />
    </navigation>
    
</navigation>

id 當(dāng)前節(jié)點(diǎn)的唯一標(biāo)識

name <fragment/> 節(jié)點(diǎn)對應(yīng)的Fragment全類名

label 節(jié)點(diǎn)說明沉删,當(dāng)與BottomNavigationView組合使用時渐尿,字符串內(nèi)容會成為頁面的title

tools:layout coding時,查看界面內(nèi)容


2.節(jié)點(diǎn)下參數(shù)配置說明

==注:== 節(jié)點(diǎn)的含義矾瑰,即表示 <Activity> <Fragment>砖茸,<DialogFragment>

圖片.png

點(diǎn)擊右上角Design,進(jìn)入Navigation,視圖導(dǎo)航編輯頁面。左側(cè)為添加一個
圖片.png

新節(jié)點(diǎn)殴穴,
圖片.png
設(shè)置某個節(jié)點(diǎn)凉夯,為首頁第一個展示節(jié)點(diǎn)。

==右側(cè)是為節(jié)點(diǎn)添加支持的屬性:==

圖片.png

2.1 跳轉(zhuǎn)當(dāng)前頁面所需參數(shù) (Argments)

跳轉(zhuǎn)采幌,回退當(dāng)前節(jié)點(diǎn)所需要的參數(shù)劲够。

Name: 參數(shù)名稱,等同于intent.getString(key,value)中的Key
Type: 參數(shù)類型
Array: 是否是數(shù)組(String[])
Nullable: 是否可以為空
Default Value 為空的時的默認(rèn)值

更多支持的參數(shù)類型:

圖片.png

2.2 跳轉(zhuǎn)路由動作 (Action)

圖片.png

ID 當(dāng)前跳轉(zhuǎn)動作節(jié)點(diǎn)的唯一標(biāo)識休傍,后續(xù)在代碼中調(diào)用navController.navigation(R.id.ID)會用到征绎,即執(zhí)行當(dāng)前配置的Action,同時也可使用想要跳轉(zhuǎn)目標(biāo)頁的ID
From 所配置的當(dāng)前節(jié)點(diǎn),點(diǎn)擊給那個節(jié)點(diǎn)配置磨取,默認(rèn)就是哪個人柿。選中后不可更改
Destination 跳轉(zhuǎn)的目標(biāo)節(jié)點(diǎn),即那個Fragment
enter:進(jìn)入動畫
Exit :退出動畫
Pop Enter : 上一節(jié)點(diǎn)出棧當(dāng)前節(jié)點(diǎn)的動畫
Pop Exit: 上一節(jié)點(diǎn)回退棧到當(dāng)前節(jié)點(diǎn)的動畫

Pop To 按返回鍵會調(diào)用 navController.navigationUp或navController.popBackStack()時忙厌,想回退定向到那個節(jié)點(diǎn)

Inclusive: 很重要 多次出現(xiàn)凫岖。加入A->B->C,C的Pop To為B,當(dāng)Inclusive 為true,則表示B也退出逢净,直接進(jìn)入到A隘截,false回退到B
Single Top 類似Activity的SingleInscance,管理棧中有相同的節(jié)點(diǎn)汹胃,則不會創(chuàng)建婶芭,同時棧內(nèi)此節(jié)點(diǎn)的上面的節(jié)點(diǎn),全部出棧着饥。

2.3 Deeplink

    <deepLink
            android:id="@+id/deepLink"
            android:autoVerify="false"
            app:action="ACTION_SEND"
            app:mimeType="text/html"
            app:uri="www.baidu.com" />

理解nav_graph.xml后犀农,在MainActivity中配置如下配置文件:

   <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

以上3個配置比較重要:

    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph"
    android:name="androidx.navigation.fragment.NavHostFragment"
  
  

三個必配項。

  1. 攔截返回鍵的點(diǎn)擊事件宰掉,這樣Fragment就可以想Activity一樣呵哨,具有回退,返回事件
  2. 配置路由XML文件轨奄,然后加載進(jìn)NavHostFragment中 app:navGraph屬性孟害,對應(yīng)的就是NavGraph這個類
  3. NavHostFragment是Navigation提供的默認(rèn)容器,所有路由邏輯都經(jīng)過這里挪拟,然后在分發(fā)出去

3. 代碼實(shí)現(xiàn)路由跳轉(zhuǎn)和方法解析

3.1 核心方法

Acitivty#findNavController() 傳入navGraph id
Fragment#findNavController() 直接調(diào)用
Navigation.findNavController() 傳入View

==navController.navigate()==

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
       super.onViewCreated(view, savedInstanceState)

       val homeText = view.findViewById<TextView>(R.id.home_text)
       homeText.setOnClickListener {

           val model = Model("Jack", 16)
           val bundle = Bundle()
           bundle.putString("home_arg_name", "Tom")
           bundle.putInt("home_arg_age", 12)
           bundle.putParcelable("home_arg_mode", model)
//            arguments?.let {
//                it.putString("home_arg_name", "Tom")
//                it.putInt("home_arg_age", 12)
//                it.putParcelable("home_arg_mode", model)
//            }

//            val navOptions = navOptions {
//                arguments?.let {
//                    it.putString("home_arg_name", "Tom")
//                    it.putInt("home_arg_age", 12)
//                    it.putParcelable("home_arg_mode", model)
//                }
//            }
           findNavController().navigate(R.id.home_to_other, bundle)
//            findNavController().navigate(R.id.home_to_other)
//            findNavController().navigateUp()
//            findNavController().popBackStack()

       }
   }

navigate() 傳入節(jié)點(diǎn)ID 表示路由到節(jié)點(diǎn)所在頁面,
傳入Action ID 表示執(zhí)行XML <Action>中的路由規(guī)則,同時還支持Deeplink跳轉(zhuǎn)

navigateUp()和popBackStack()都表示回退上頁面挨务,但navigateUp()在Deeplink的情況下 應(yīng)用1a(deeplink)路由到應(yīng)用2的B后navigateUp()返回到a,而popBackStack()則會返回到當(dāng)前棧內(nèi)的上一層(A)
另一個區(qū)別是popBackStack()支持回退到指定頁面,inclusive參數(shù)谎柄,之前有提到過

bundle 設(shè)置傳遞參數(shù) Options設(shè)置其他配置參數(shù)丁侄,如動畫,popUpTo等朝巫,也就說鸿摇,在XML中的配置,在代碼中都可實(shí)現(xiàn)劈猿。
那么參數(shù)中的配置argument在什么場景下比較合適拙吉。答案是:一些固定配置參數(shù)。例如loginFragment揪荣。A,B頁面都會進(jìn)入Login頁面庐镐,但它們有不同的權(quán)限,所以可以配置不同的type变逃,且這種配置基本不會變化必逆。

4. 源碼分析

4.1 源碼中出現(xiàn)的個各類和職責(zé)
Navigation分析圖.png

下篇將從這張圖入手,開始源碼分析揽乱,并利用實(shí)戰(zhàn)改造

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末名眉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凰棉,更是在濱河造成了極大的恐慌损拢,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撒犀,死亡現(xiàn)場離奇詭異福压,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)或舞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進(jìn)店門荆姆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人映凳,你說我怎么就攤上這事胆筒。” “怎么了诈豌?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵仆救,是天一觀的道長。 經(jīng)常有香客問我矫渔,道長彤蔽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任庙洼,我火速辦了婚禮顿痪,結(jié)果婚禮上镊辕,老公的妹妹穿的比我還像新娘。我一直安慰自己员魏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布叠聋。 她就那樣靜靜地躺著撕阎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碌补。 梳的紋絲不亂的頭發(fā)上虏束,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天,我揣著相機(jī)與錄音厦章,去河邊找鬼镇匀。 笑死,一個胖子當(dāng)著我的面吹牛袜啃,可吹牛的內(nèi)容都是我干的汗侵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼群发,長吁一口氣:“原來是場噩夢啊……” “哼晰韵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起熟妓,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤雪猪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后起愈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體只恨,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年抬虽,在試婚紗的時候發(fā)現(xiàn)自己被綠了官觅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡阐污,死狀恐怖缰猴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疤剑,我是刑警寧澤滑绒,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站隘膘,受9級特大地震影響疑故,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弯菊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一纵势、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦钦铁、人聲如沸软舌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佛点。三九已至,卻和暖如春黎比,著一層夾襖步出監(jiān)牢的瞬間超营,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工阅虫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留演闭,地道東北人。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓颓帝,卻偏偏與公主長得像米碰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子购城,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內(nèi)容