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.