AndroidX — 如何使用Navigation的 Safe Args更安全的傳遞兩個Fragment的參數

JLin
Nov 18, 2020

--

https://developer.android.com/guide/navigation/navigation-pass-data

這是一個已經很久的功能,不過之前在看的時候還是在beta 版本,所以也一直沒有把他用在產品上面,然後最近看到已經在正式版本了

以github的NaivagationSample來看

如果從

LeaderBoard.kt ->UserProfile.kt 

需要帶入參數

userName: String

以往我們傳遞參數在兩個fragment之間都需要透過

可以看到都需要額外定義一個bundleKey,”userName”,當然可以把它定義成一個常數,但有時候又會忘記key名稱是什麼要找半天,再傳送端要寫使用這個key

在使用端的又要寫這個key,如果key一多整個就會非常的混亂,為了避免這樣的情形,於是Jetpack推出了一個叫做Navigation SafeArgs的 code generate的工具(或稱外掛),需要先定義

並且在app的gralde定義

因為他是一個根據程式動態產生的類別的方式,所以需要這樣的進行設定

重點來了

當你在navigation xml中定義該fragment的argument 後,Safe Args就會自動幫你產生一個Directions class

以往你需要透過這種R.id.xxxx的方式去跳轉fragment並且代入寫好的bundle

val bundle = bundleOf("userName" to myDataset[position])

Navigation.findNavController(holder.item).navigate(
R.id.action_leaderboard_to_userProfile,bundle)

就可以取代成

val naviDirect = LeaderboardDirections.actionLeaderboardToUserProfile(userName)
Navigation.findNavController(holder.item).navigate(naviDirect)

原本的LeaderBoard會產生另一個叫做 LeaderBoardDirections的類別,並且以面有建立好前往其它頁面的方法

LeaderBoardDirections.actionLeaderboardToUserProfile(userName: String)

在資料使用端 UserProfile.kt中如何抓取資料?

另一個重點來了,Safe Args會幫你產生另一個Class,叫做UserProfileArgs

如果你是使用ktx,在UserProfile.kt中可以很簡單的定義一個naviArg變數,並且使用kotlin 的by功能

val args : UserProfileArgs by navArgs()

這樣就可以直接使用了,因為結果已經被解析後存到這個args中了,你可以直接使用

原本

val name = arguments?.getString("userName") ?: "Ali Connors"

變成

val name = args.userName

不再需要string的 bundle key name,不再需要撰寫非常長的程式碼,如果你有多個參數傳入,將會更方便

寫得有點雜,但還是希望能夠有幫助到對於傳遞參數有困擾的人,透過這種方式可以解省時間去定義Bundle或是寫keyName,或是要自己另外自訂ArgumentHelper之類的行為,另一個方便的點是他會跟著navigation xml定義的參數自動產生,雖然個人不太喜歡這種auto generate code的工具,但這真的可以減少一些人為疏失與後期管理的問題

簡單一點可以變成下圖這樣

done.

--

--

JLin
JLin

Written by JLin

台中 / JAVA / Android /Kotlin / Kotlin Native 對於Kotlin衍生的JVM等技術 Compose for web / desktop / Ktor Server,生成式AI (Gemini/OpenAI)各式應用, 都有小興趣

No responses yet