日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android Jetpack Navigation 深入体验报告

發(fā)布時(shí)間:2025/3/21 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Jetpack Navigation 深入体验报告 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android Jetpack 之 Navigation深入體驗(yàn)報(bào)告

前言

當(dāng)前Android開(kāi)發(fā)中使用Fragment來(lái)開(kāi)發(fā)頁(yè)面已經(jīng)成為主流做法。Fragment輕量、可控性強(qiáng)等優(yōu)點(diǎn)讓人感覺(jué)很香。

但是Fragment也有自己的硬傷,那就是回退棧與頁(yè)面參數(shù)傳遞。雖然當(dāng)前有例如Fragmentation這樣的開(kāi)源庫(kù)解決了這類問(wèn)題,而且這些三方開(kāi)源庫(kù)也經(jīng)受住了時(shí)間與項(xiàng)目的檢驗(yàn)。但是總讓Android開(kāi)發(fā)者心中覺(jué)得少了點(diǎn)什么(尤其是學(xué)了iOS開(kāi)發(fā)之后。。。)

Navigation的橫空出世,讓Android開(kāi)發(fā)者終于看到了一線曙光。

上手接入

看到這么個(gè)好藥,能治Android開(kāi)發(fā)者的心病,我就抱著試試看的態(tài)度買了兩盒,額,不對(duì),是接入了一下。

其實(shí)接入方法非常簡(jiǎn)單,就是一頓添加依賴。Navigation主要是有兩個(gè)庫(kù)和一個(gè)gradle插件。

// 需要添加依賴的兩個(gè)Navigation庫(kù) implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0-beta02' implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0-beta02'// 這段依賴添加在工程的build.gradle中,這個(gè)是一個(gè)gradle插件 classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-beta02'// 在app用到的module中啟用這個(gè)插件 apply plugin: 'androidx.navigation.safeargs' 復(fù)制代碼

兩個(gè)依賴庫(kù)就是Navigation的主體,提供了Navigation的基礎(chǔ)能力。safeArgs這個(gè)插件是用來(lái)支持頁(yè)面間類型安全的參數(shù)傳遞,不是必須的,但是建議使用,因?yàn)檎娴暮芊奖?#xff0c;這個(gè)后面會(huì)講到。

創(chuàng)建一個(gè)Navigation

依賴都添加好了,開(kāi)搞!

Navigation還是延用了Android的XML管理思想,每一個(gè)Navigation導(dǎo)航邏輯對(duì)應(yīng)一個(gè)xml文件(就是對(duì)應(yīng)iOS的storyboard)。這個(gè)xml文件在資源目錄的navigation文件夾下(和layout、drawable是平級(jí)的)

創(chuàng)建方法就是右鍵,選擇new一個(gè)Android Resource File,之后的彈窗里,你會(huì)發(fā)現(xiàn)ResourceType的選項(xiàng)里,多了一個(gè)Navigation,如下圖。(如果沒(méi)有,老弟兒,你的依賴一定沒(méi)配置對(duì),或者你還是AndroidStudio3.2吧。。。)

起個(gè)名字,創(chuàng)建!操作面板長(zhǎng)成這樣(不要在意我風(fēng)騷的名字)

我的需求很簡(jiǎn)單,我有一個(gè)桌面頁(yè)(desktop),我現(xiàn)在想上youtube,我先要跳轉(zhuǎn)的Google,然后在通過(guò)Google上youtube去看看外面的世界,完事以后回到桌面。嗯,就這么簡(jiǎn)單。

按照以前我們的做法,首先肯定要自己創(chuàng)建3個(gè)頁(yè)面的Fragment布局,然后再創(chuàng)建Fragment類,然后還要在Activity里面創(chuàng)建三個(gè)Fragment,然后通過(guò)SupportFragmentManager來(lái)添加頁(yè)面,管理頁(yè)面跳轉(zhuǎn)和回退,這個(gè)就是我們開(kāi)篇時(shí)候說(shuō)的痛點(diǎn)。

現(xiàn)在有了Navigation,怎么做呢?放下一前的老思想吧,不用寫代碼就能搞定。

首先,在剛才的面板中點(diǎn)擊添加一個(gè)destination,destination(目的地)是一個(gè)新概念,用于頁(yè)面跳轉(zhuǎn)。一個(gè)destination對(duì)應(yīng)一個(gè)Fragment。例如從A跳轉(zhuǎn)B,我的destination就是B。

創(chuàng)建destination的過(guò)程非常人性化,填寫Fragment名字,自動(dòng)創(chuàng)建對(duì)應(yīng)的xml布局文件。我們就添加三個(gè)頁(yè)面,Desktop、Google、youtube。添加完如圖所示:

OK,我們用到的3個(gè)頁(yè)面都在這里了。我們的跳轉(zhuǎn)流程就是Desktop - > Google -> youtube -> Desktop。怎么設(shè)置呢?連線就行了!

連線完畢是這樣的,不要在意那飄逸的線條。Desktop頁(yè)面左上角有個(gè)小房子圖標(biāo),這說(shuō)明這個(gè)頁(yè)面是Navigation的起始頁(yè)面。這個(gè)可以在右側(cè)編輯欄里的start destination中修改。

關(guān)聯(lián)Navigation到Activity

聯(lián)好線了,走到這一步,我們已經(jīng)將頁(yè)面的跳轉(zhuǎn)關(guān)系聲明完畢。但是要提醒大家一下,我們編輯的這個(gè)Navigation是一個(gè)xml,而且是一個(gè)導(dǎo)航xml,并不是布局啊。怎么往頁(yè)面里添加呢?

別急,這個(gè)也很簡(jiǎn)單。先在Activity的布局xml里添加一個(gè)fragment標(biāo)簽。然后添加navi屬性,具體如下:

<fragmentandroid:id="@+id/nav_host_fragment"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:defaultNavHost="true"app:navGraph="@navigation/navi_youtube"/> 復(fù)制代碼

關(guān)鍵屬性有兩個(gè)個(gè),android:name app:navGraph

name中聲明這個(gè)Fragment是一個(gè)NavHostFragment。這個(gè)可以理解為所有導(dǎo)航頁(yè)面的容器。導(dǎo)航中聲明了各個(gè)頁(yè)面的跳轉(zhuǎn)關(guān)系,但是總要有一個(gè)容器來(lái)展示并控制它們吧?這個(gè)容器就是NavHostFragment,然后創(chuàng)建一個(gè)Activity,用這個(gè)Activity再包一下NavHostFragment就可以了。

navGraph屬性指定一個(gè)導(dǎo)航xml,就是我們剛才編輯的那個(gè)navi_pornhub。

配置完了就可以運(yùn)行一下看看效果了,果然啟動(dòng)后進(jìn)入了Desktop頁(yè)面(這里懶得截圖了。。。)

頁(yè)面間的跳轉(zhuǎn)

看的這里可能各位會(huì)說(shuō),這玩意除了一個(gè)圖形化的編輯界面就完事了?這個(gè)我用原來(lái)的純代碼也能做啊。。。它的優(yōu)勢(shì)在哪?難道只是長(zhǎng)得好看嗎?

各位別急啊

以前頁(yè)面的跳轉(zhuǎn)怎么做?SupportFragmentManager用FragmentTransaction,自己管理,寫好多行代碼。

看看現(xiàn)在的新操作:

在Desktop頁(yè)面中點(diǎn)擊TextView跳轉(zhuǎn)Google,只需要在onClick里加入這樣一行代碼即可:

tv_desktop.setOnClickListener {findNavController().navigate(FragmentDesktopDirections.actionFragmentDesktopToFragmentGoogle()) } 復(fù)制代碼

加完之后運(yùn)行一下,發(fā)現(xiàn)真的可以跳轉(zhuǎn)了!

我們來(lái)仔細(xì)看看這行魔法代碼。首先它執(zhí)行findNavController(),這個(gè)函數(shù)點(diǎn)進(jìn)去發(fā)現(xiàn)它是Navigation庫(kù)給Fragment做的一個(gè)拓展。

這里有就是調(diào)用了NaviHostFragment的同名函數(shù),這也印證了我們前文說(shuō)到的NaviHostFragment的作用,它就是一個(gè)控制容器。

找到NavController之后,調(diào)用了navigate(NavDirections directions)函數(shù)。這個(gè)函數(shù)從名字看出來(lái)就是做導(dǎo)航跳轉(zhuǎn)用的。但是新姿勢(shì)是它的參數(shù)比較特殊,是一個(gè)NavDirections實(shí)例。這個(gè)類是干什么的呢?

還記得前面介紹的Destination概念嗎?Destination表示一個(gè)跳轉(zhuǎn)目的地,一個(gè)Destination對(duì)應(yīng)一個(gè)Fragment。NavDirections表示的是兩個(gè)頁(yè)面之間的跳轉(zhuǎn)關(guān)系,其實(shí)就是我們最開(kāi)始畫導(dǎo)航頁(yè)面關(guān)系時(shí)候,連接頁(yè)面的那個(gè)箭頭。一個(gè)箭頭對(duì)應(yīng)一個(gè)NavDirections實(shí)例。

那跳轉(zhuǎn)的時(shí)候如何獲取NavDirections實(shí)例呢?這里Navigation框架采用編譯器自動(dòng)生成代碼的技術(shù),對(duì)導(dǎo)航xml每一個(gè)Fragment,都生成了一個(gè)對(duì)應(yīng)的類,名字就是類名+Directions,例如FragmentGoogleDirections。這些自動(dòng)生成的類可以在工程的generatedJava路徑下看到。代碼如下:

其實(shí)就是一個(gè)Java靜態(tài)工具類。有一個(gè)action,名字就可以看出是由桌面跳轉(zhuǎn)Google,它返回一個(gè)NavDirections實(shí)例。所以在跳轉(zhuǎn)頁(yè)面時(shí),我們直接調(diào)用這個(gè)函數(shù)獲取NavDirections實(shí)例即可。這個(gè)實(shí)例就包含了頁(yè)面跳轉(zhuǎn)信息,告訴Navigation我要從桌面跳轉(zhuǎn)的Google頁(yè)面。

這里只有一個(gè)跳轉(zhuǎn)action函數(shù),因?yàn)樽烂嬷挥刑D(zhuǎn)Google一個(gè)跳轉(zhuǎn)管理。如果頁(yè)面增加,桌面有多條跳轉(zhuǎn)關(guān)系,這里會(huì)生成多個(gè)action函數(shù),函數(shù)名稱對(duì)應(yīng)導(dǎo)航xml中每個(gè)箭頭的action名稱。

同理,把Google跳轉(zhuǎn)youtube,和youtube跳轉(zhuǎn)桌面也加上,都很簡(jiǎn)單。

tv_google.setOnClickListener {findNavController().navigate(FragmentGoogleDirections.actionFragmentGoogleToFragmentYoutube()) }tv_youtube.setOnClickListener {findNavController().navigate(FragmentPornHubDirections.actionFragmentYoutubeToFragmentDesktop()) } 復(fù)制代碼

這樣就實(shí)現(xiàn)了頁(yè)面間的跳轉(zhuǎn)邏輯。這種寫法首先很簡(jiǎn)潔,思路清晰,看函數(shù)名一眼就能看出來(lái)是怎么跳轉(zhuǎn)的,而且自動(dòng)生成的代碼也避免了人為犯錯(cuò)。怎么樣,回想一下以前用SupportFragmentManager做跳轉(zhuǎn)的方法,是不是感覺(jué)相見(jiàn)恨晚?

頁(yè)面回退管理

了解了頁(yè)面跳轉(zhuǎn),我們?cè)賮?lái)看看頁(yè)面回退。運(yùn)行一下剛才的程序,發(fā)現(xiàn)可以無(wú)限循環(huán)跳轉(zhuǎn),桌面到Google,Google到y(tǒng)outube,youtube再到桌面。。。

我們點(diǎn)一下返回鍵看看會(huì)發(fā)生什么。額。。。發(fā)現(xiàn)會(huì)一直回退,你剛才重復(fù)循環(huán)了跳轉(zhuǎn)多少次,就要回退多少次。這個(gè)說(shuō)白了就是Activity的Standard啟動(dòng)模式。

這個(gè)不是我們要的效果啊,我們要的是A到B,B到C,C返回A,之后頁(yè)面棧里就只有A了。不能再返回了。說(shuō)白了就是singleTask啟動(dòng)模式。

這個(gè)需要對(duì)跳轉(zhuǎn)的屬性進(jìn)行設(shè)置,打開(kāi)導(dǎo)航xml,選中youtube到桌面的連接箭頭。在右側(cè)的屬性編輯區(qū)里,找到紅框里的屬性,填寫好即可。

這里首先聲明了這是一個(gè)pop跳轉(zhuǎn)操作,要跳回到Desktop。然后inclusive打上對(duì)勾,這個(gè)表示調(diào)回之后,要把destination也彈出。不勾選這個(gè),會(huì)導(dǎo)致返回后棧里有兩個(gè)桌面Fragment。不信可以試試哦。

之后再你的Activity里面,覆寫這個(gè)函數(shù):

override fun onSupportNavigateUp() =findNavController(this, R.id.nav_host_fragment).navigateUp() 復(fù)制代碼

覆寫這個(gè)函數(shù)就是把Activity的返回操作權(quán)利移交給Navigation框架來(lái)處理。從此不用再寫onKeyDown了。。。

頁(yè)面參數(shù)傳遞

跳轉(zhuǎn)和回退都搞定了,就要看看頁(yè)面參數(shù)傳遞了。這個(gè)體驗(yàn)之后發(fā)現(xiàn)是真香度最高的部分。

先回顧一下老方法,老方法當(dāng)然就是setArguments。因?yàn)镕ragment不支持你在構(gòu)造函數(shù)中加入?yún)?shù)(當(dāng)然你要硬加也行,各種報(bào)警告,賊難受),所以只能通過(guò)setArguments來(lái)搞,不管你怎么封裝,都需要兩步:創(chuàng)建和設(shè)置參數(shù)。怎么都不快樂(lè)。

現(xiàn)在來(lái)Navigation吧,這個(gè)新操作絕對(duì)眼前一亮。

需求:我想在桌面跳轉(zhuǎn)Google時(shí),給頁(yè)面?zhèn)鬟f一個(gè)搜索關(guān)鍵詞youtube,并且彈一個(gè)Toast。下面是做法:

首先在導(dǎo)航xml里,選中GoogleFragment,在右面的操作面板里,點(diǎn)擊添加arguments,添加一個(gè)字符串參數(shù),叫keyword。不可空,沒(méi)有默認(rèn)值。點(diǎn)擊確認(rèn)添加。

之后可以看見(jiàn)GoogleFragment里面已經(jīng)有一個(gè)叫keyword的參數(shù)了。

之后點(diǎn)擊桌面到Google的箭頭(還記得箭頭其實(shí)就是一個(gè)NavDirections吧),你會(huì)發(fā)現(xiàn)這個(gè)Direction的屬性里也有了一個(gè)參數(shù),其實(shí)這個(gè)就是一個(gè)自動(dòng)化的對(duì)應(yīng)機(jī)制,因?yàn)镚oogleFragment有一個(gè)參數(shù),所以所有跳轉(zhuǎn)到這個(gè)頁(yè)面的Direction里都應(yīng)該有對(duì)應(yīng)的參數(shù)。

參數(shù)添加好以后,修改一下跳轉(zhuǎn)的那一行魔法代碼。

tv_desktop.setOnClickListener {findNavController().navigate(FragmentDesktopDirections.actionFragmentDesktopToFragmentGoogle("youtube")) } 復(fù)制代碼

這里在調(diào)用action函數(shù)獲取NavDirections實(shí)例的時(shí)候,需要傳一個(gè)字符串,就是keywork的值。同理如果有多個(gè)參數(shù)這里就傳多個(gè)值。

OK,啟動(dòng)方的參數(shù)傳遞已經(jīng)完成了。我們來(lái)看看接收方。

在GoogleFragment中如何獲取到keyword的值呢?其實(shí)Navigation庫(kù)已經(jīng)幫你把參數(shù)放到arguments里面了,你直接取就行了。例如這樣:

val keyword = arguments?.getString("keyword") ?: "" 復(fù)制代碼

直接這么調(diào)用就能拿到傳遞過(guò)來(lái)的值了。但是感覺(jué)不是很香啊。那是因?yàn)槟銢](méi)有使用safeArgs插件!來(lái)看一下這個(gè)新操作。

val safeArgs = FragmentGoogleArgs.fromBundle(arguments!!) val keyword = safeArgs.keyword 復(fù)制代碼

這里又用到了自動(dòng)生成代碼的技術(shù),對(duì)于每一個(gè)有參數(shù)的Fragment,都生成一個(gè)類名+Args的類。調(diào)用第一行代碼,就能得到一個(gè)safeArgs實(shí)例。之后需要用參數(shù)的時(shí)候,直接safeArgs.參數(shù)名就能拿到參數(shù)的值。

各位老鐵,感覺(jué)出safeArgs的好處了嗎?首先它是類型安全的,可以直接點(diǎn)出來(lái),不用打問(wèn)號(hào),舒服了很多。最重要的是,老方法是getString("變量名")這個(gè)變量名是手打的,safeArgs可以直接點(diǎn)出變量名來(lái)取值,方便還不容易出錯(cuò)。

體驗(yàn)總結(jié)

  • 真香
  • 目前還是beta版本,還不建議在實(shí)際項(xiàng)目中使用
  • 會(huì)持續(xù)關(guān)注后續(xù)消息,期待穩(wěn)定版本
-- 2019.03.18更新,已發(fā)布1.0.0正式版

轉(zhuǎn)載于:https://juejin.im/post/5c8f283f6fb9a0710466981a

總結(jié)

以上是生活随笔為你收集整理的Android Jetpack Navigation 深入体验报告的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。