一、什么是navigation
要說什么是navigation就要先說說fragment這個東西。fragment最早出現(xiàn)在Android 3.0,它的出現(xiàn)主要伴隨著兩個目的:
- 用于適配當時搭載蜂巢的Android平板設(shè)備,讓其在更大的屏幕上能夠在一個activity嵌套多個不同的頁面,充分的利用大屏的顯示優(yōu)勢。

- 分散activity的壓力,對其解耦,讓部分UI內(nèi)容由各個fragment獨自管理。
fragment有非常多的優(yōu)勢,它本身是一個VIew派生而來的控件,嵌套靈活,渲染所消耗的資源明顯小于activity,數(shù)據(jù)的傳遞也更加方便,當然它的優(yōu)點并不止這些,
以至于包括知乎、Google全家桶在內(nèi)的眾多App都發(fā)展出了單Activity+多fragment的方式開發(fā)UI,這其中的優(yōu)勢,在知乎的一個問題下有著非常多討論。https://www.zhihu.com/question/39662488
但是在在這些應(yīng)用開發(fā)的過程中,開發(fā)者們也發(fā)現(xiàn)了不少這種做法帶來的坑。例如需要維護復(fù)雜的fragment回退棧、使用不當?shù)那闆r下經(jīng)常出現(xiàn)fragment重疊、經(jīng)常由于activity已經(jīng)銷毀導致使用上下文crash、
等等等等的問題。
而navigation就是為了解決這些問題而出現(xiàn)的,用于實現(xiàn)單activity多fragment形式的官方解決方案。
navigation是jetpack組件庫的一部分,jetpack的前生其實就是我們所熟悉的support library,Google在不久前宣布support library將只維護到v28,之后將全面遷移到androidx(也就是jetpack)。
二、添加navigation支持
navigation的使用限制實際上是比較多的。
- 保證你的Android studio版本 >=3.2
-
保證項目的gradle版本>=3.2
image -
保證項目sdk的版本>=28
image - 將你的項目從support library 向 androidx遷移,這一點工程量比較大,所以Google在新版studio添加了一鍵遷移程序。

- 確保studio打開了navigation的支持,在設(shè)置中確保如下開關(guān)是打開的。

這幾步你都做完了嗎?做完了就可以在你的gradle下添加navigation的依賴了。
implementation "android.arch.navigation:navigation-fragment:1.0.0-alpha07"
implementation "android.arch.navigation:navigation-ui:1.0.0-alpha07"
三、使用navigation
使用起來其實蠻簡單的 ,首先在res目錄下新建一個android resource file ,名稱有意義即可,resource type 選擇 navigation

得到這樣一個文件,由于還沒有任何的頁面,所以只有一個節(jié)點navigation


新增頁面。這里既然要跳轉(zhuǎn),我們新增兩個fragment。
選中一個頁面的時候,右側(cè)會有針對這個fragment的屬性面板,而fragment本身會出現(xiàn)一個小圓點,此時我們就可以拖拽這個小圓點去連接其他的頁面,連接上就表示建立了跳轉(zhuǎn)關(guān)系了。

這時打開text視圖可以看到多了兩個fragment節(jié)點,并且在第一個fragment節(jié)點下多了一個action。
之后我們的跳轉(zhuǎn)就需要通過這個action的id來實現(xiàn)了。
現(xiàn)在打開BlankFragment的布局,為其添加一個用于跳轉(zhuǎn)的按鈕。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment">
<Button
android:id="@+id/mJumpBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="jump to second fragment"/>
</FrameLayout>
在fragment中,該按鈕點擊事件被觸發(fā)后,使用Navigation調(diào)用findNavController傳入觸發(fā)事件的view的對象獲取到一個NavController對象,調(diào)用其navigate方法傳入前面所提到的action的id,即可完成跳轉(zhuǎn)。
mJumpBtn.setOnClickListener { view ->
Navigation.findNavController(view).navigate(R.id.action_blankFragment_to_secondFragment)
}
現(xiàn)在fragment之間的跳轉(zhuǎn)已經(jīng)搞定,但是我們卻忘了,fragment還需要依賴activity去展示呢,那么我們找回一開始新建項目得到的MainActivity(沒有的話自己新建一個哦)。
打開MainActivity的布局。在布局中添加一個fragment,注意紅框標注的那兩段代碼,會將我們前面寫好的navigation嵌入進來。

至此,運行程序,你會發(fā)現(xiàn),展示的第一個頁面是帶有jump to second fragment 按鈕的BlankFragment,點擊它會跳轉(zhuǎn)到第二個SecondFragment。觸摸手機的返回鍵會返回到上一個頁面,和activity幾乎一樣。
如果你使用的是toolbar,那么可以直接綁定這兩個控件來完成toolbar返回的操作,如果不是,那么你可以在SecondFragment中獲取到NavController并調(diào)用navigateUp方法來返回上一個頁面
mBackBtn.setOnClickListener {
Navigation.findNavController(it).navigateUp()
}
四、傳遞參數(shù)
傳遞參數(shù)其實很簡單,和我們之前傳遞的方式其實類似,同樣是使用bundle來傳遞。
傳遞
mJumpBtn.setOnClickListener { view ->
Navigation.findNavController(view).navigate(R.id.action_blankFragment_to_secondFragment, Bundle().apply {
putString("name", "tracy")
putInt("age", 35)
})
}
接收
arguments?.let {
Log.i("日志", it.getString("name"))
Log.i("日志", it.getInt("age", 0) + "")
}
五、其他能力
當然,navigation所提供的能力遠不止這些。
在傳參方面它可以通過gradle插件的方式為我們提供更可靠安全的數(shù)據(jù)傳遞。
它能更簡單的為fragment添加跳轉(zhuǎn)動畫
它能讓fragment實現(xiàn)共享元素動畫
它能通過Deep Link直接路由到fragment
它能直接與androidx組件中的 NavigationView(對,就是側(cè)滑抽屜用的那個)進行菜單聯(lián)動
它能和menu浮層菜單進行聯(lián)動
也能和toolbar進行聯(lián)動
此文只講解了比較基礎(chǔ)的使用方式,還有很多功能請查看api哈。