穿梭在不同的畫面中 - 動態名稱與資料傳送
WriterShelf™ is a unique multiple pen name blogging and forum platform. Protect relationships and your privacy. Take your writing in new directions. ** Join WriterShelf**
WriterShelf™ is an open writing platform. The views, information and opinions in this article are those of the author.
Article info
This article is part of:
Categories:
Tags:
Date:
Published: 2021/06/11 - Updated: 2021/09/18
Total: 4168 words
Like
or Dislike
About the Author
很久以前就是個「寫程式的」,其實,什麼程式都不熟⋯⋯
就,這會一點點,那會一點點⋯⋯
More to explore
Flutter 提供了四種 Navigation & Routing 的方式:
前面我們已經學會「N1 直接導航」及「N2 固定名稱路由」,現在讓我們來看看:
N3 動態名稱路由:
延續我們的程式碼,它已經準備好可以用來測試動態名稱路由了。如果有人現在才加入,目前階段的程式碼請自行參考本書:程式碼備份中的 Code milestone 1。
什麼是「動態名稱路由」?
其實就是要能有如下的這個網址:
www.url.com/audio/8
重點就是那個有底線的 8,它是變動的,之前介紹的方法都沒有辦法做到,「N1/直接導航」法根本就沒有路由名稱,也就是 audio 部分,「N2/固定名稱路由」法只能走固定的路由名稱, 所以,才有這第三個方法,為了支援動態的路由名稱,「N3/動態名稱路由」才出現了,哎,這一切的一切都是為了要支援網站啊。
等等,發明了那麼多方法,就是為了支援網頁?不是為了要傳那個參數「8」嗎?是的,答案是:不是,每一個方法都可以傳參數!不信我們就先來看看:
用 N1/直接導航,傳參數
先來寫接收端,我們透過 MyHomePage 來選要讀取那一筆資料,顯示在 AudioSession 上,所以 接收端是 AudioSession:
lib/screens/audio_session.dart:
再來就是要顯示出 AudioRec 的資料,如下,在同一個 audio_session.dart 內:
就這樣,接收端就寫好了,再來就是傳送端了:
lib/screens/my_home_page.dart 中,要將 ListView 中的每一個 card 建立一個相對的跳轉:
就這樣,傳送端也寫好了,只是我們的 myApp 報錯了,我們在 routes 中的 AudioSession 必須要有 arIndex 參數:
lib/main.dart 中:
第 3 行:呼叫 AudioSession 必須要有參數,這個 route 目前只有 MyHomePage 的 FloatingActionButton 在用,它未來會是個新增動作,還沒寫,所以就先讓它傳 0 吧,也就是讓它顯示第一筆資料。
好了,現在可以試試了,讚!點選任何一個列表項目,就可以看到它相對的內容了,所以,我們證明了「N1/直接導航」是可以傳參數的!
在網頁上也動作正常,只是,它的網址不是 www.url.com/audio/8,如我們所預期,網址如下,空空如也:
結論:「N1/直接導航」是可以傳參數的,而且簡單好用,除非你一定要在瀏覽器上能顯示動態網址列,才需要使用「N3/動態名稱路由」
用 N2/固定名稱路由,走 ModalRoute 傳參數
剛剛的網址空空如也,那如果用「N2/固定名稱路由」法,就能產生我們要的網址嗎?不知道,試試就知道。
「N2/固定名稱路由」法是透過 ModalRoute 來傳參數,方法也很簡單:
聽無啦,講一堆不如直接上碼,延續上面的程式,接收端完全不用改,只有傳送端更改如下。
lib/screens/my_home_page.dart 中:
第 5 行:一樣要將 ListView 中的每一個 card 建立一個相對的跳轉,只是這次改呼叫 Navigator 的pushNamed,目標 screen 就是一個在 named route 中的固定名稱路由,這也都學過了,唯一新的東西就是加了一個 arguments: index,是的,我們可以透過 arguments 在「固定名稱路由」法中傳送參數。
下面的 FloatingActionButton 也要改一下,這個按鈕未來是要做新增的,目前就先把他指到 0 吧。
lib/screens/my_home_page.dart 修改位於最下面 FloatingActionButton 的 Navigator:
第 4 行:只是新增了一個 arguments: 0 參數。
好啦,再來就是要改 route 了:
lib/main.dart 中:
我們再花一點時間來看這行:
!
尾巴的驚嘆號是 dart 的 “Casting away nullability”,這樣寫是保證左邊的值一定不是 null,這是為了要合乎 Dart 的 null safety 寫法,在 Flutter/Dart 中,我們要很明確的告知每個物件是不是 null,當有模糊不清時,編譯器就會報錯,這就是 null safety 保護,當然,你只是「告訴」編譯器它不會是 null,如果執行時,它真的是 null 時,程式就會死給你看。好了,現在可以試試了,又是讚!所以固定名稱路由也可以傳參數的,在網頁上也動作正常,只是,它還是不是我們要的 www.url.com/audio/8 網址,如下,有好一點了,但是還是沒有「8」!
註:如果你要傳兩個以上的參數,可以用 Map 或是另建一個 class。
N3/動態名稱路由,用 onGenerateRoute 來傳參數
除了用 ModalRoute 以外,如果是使用 MaterialApp 或 CupertinoApp 還有另一個方法:onGenerateRoute 可以用,一樣,先來上碼,廢話少說:
lib/main.dart:
return
null
, 它就會回到 default route name,你沒改的話就是 /,也就是 root screen。等等,你有注意到那個
(_) => func()
了嗎?那是什麼鬼啊? 其實這又是 dart 的一個簡寫,在 dart 中,我們已經知道底線是指 priavate 變數,但是它有例外,它也可以是「無用參數」的名稱,而且可以寫成 _、__、___ 也就是寫成一個、兩個或三個底線,效果跟寫成() => func()
一樣。你會說那就跟傳 null 是一樣了,沒錯,只是在 dart 中,null 是 keyword,你不能用來當參數名稱。傳送端還是一樣,所以不用改,但是我們現在可以處理不知名的 404 路由了,所以可以先將還沒有寫好的路由放上去,反正沒有路就會到 404。
lib/screens/my_home_page.dart
好啦,基本上這樣就改好了,啊,對了,我們還沒有寫 Page404 screen:
Android Studio 很聰明,當你新增這個程式檔案後,面對一個空白的頁面,你只要打 st 就會跳出程式樣板選項,如下,選一個你要的,就幫你寫好樣板了,404 不用會動吧,所以就用 stless = Stateless 就好了,反正以後改道 Stateful 也很方便。
套個 Scaffold,加上幾個 Widget 就像個樣了,各位也可以自己發揮想像力,404 是個工程師的玩具,很多網站的 404 都設計的很酷。
lib/screens/page_404.dart:
這個程式內容大家應該已經很熟悉了,都已經看了好幾次了,就是一個 StatelessWidget,但是我們還是再來看一下:
好啦,可以試試看了,很好,行動裝置與網站都如預期的運行正常,動態名稱路由也確定可以傳參數,只是,在網頁上,它完全做不到我們要的 www.url.com/audio/8 網址,連 /audio 都不見了:
同時,每個方法都一樣,網頁跳轉都無法由瀏覽器網址來操作,這樣是正常的嗎?
答案是:是的,這三種辦法都沒有辦法提供瀏覽器網址操作,也不能顯示我們所要的動態網址。
onUnknownRoute
如果不想使用 onGenerateRoute,要用「N2/固定名稱路由」法時,怎麼處理 404 呢?很簡單,就用 onUnknownRoute,如下:
記得要把原來 onGenerateRoute 的部份刪掉,沒刪掉雖然不會怎樣,程式反正根本不會走到下面了,但是未來要回頭改程式時,一定會很亂。
傳回參數
我們也可以用 Navigator.pop 傳回參數,只要用 Pop 夾帶:
在 push 端用個變數接收:
很簡單吧,_backMsg 就會得到 "傳回這字串" 了!
Flutter on Web 的強項
是的,Flutter 好像不能用來取代其他的網頁開發平台 ,但是,我們要回歸需求的原點,Flutter 是跨平台的開發環境,它的 Web 網頁本質上是要提供跟「行動裝置」一樣的使用者體驗,它並不適合用來開發一般傳統的 HTML 網站,是的,它也許不適合用來架設 blog 網站,但是下面的幾種新一代的網站技術,卻又是 Flutter on Web 的強項:
所以,Flutter 做不到我們要的 www.url.com/audio/8 網址嗎?答案是:做得到,只是會很麻煩,要用 Flutter 的「N4/動態名稱路由 2.0,Navigator 2.0」,或是使用外掛,如:Fluro。
動態名稱路由 2.0,也就是 Navigator 2.0,會使用到 App 狀態 state, 所以我們會等到介紹完 state 後,再回來談它了。
Bouns ~ Hero 動畫初體驗!
在結束前,還要分享一個很酷又簡單的導航功能,Flutter 的導航有提供一個非常簡便的動畫轉場方法,the HERO!
行動裝置的使用者體驗,也就是大家常掛在嘴上的 UX,有很多是透過動畫來達成的,Flutter 當然支援動畫,只是要使用它並不容易,我們還沒學到,也還不會用,不過Flutter 導航有一個很簡單好用的 Hero widget,只要兩行就把動畫帶上線了!
要使用 Hero Widget 超級簡單,只要把「起點」跟「終點」的 Widget 用 Hero() 包起來就好,所以在我們目前的程式中,「起點」就是:
lib/screens/my_home_page.dart:
「起點」有了,再來就是「終點」:
lib/screens/audio_session.dart:
「終點」widget 不能亂選,做好是跟「起點」的 widget 樹是一樣的,在我們的程式裡,剛好「終點」有個 Card widget,裡面也幾乎跟「起點」的 widget 一樣,用動畫連接這兩個 widget 也很傳神的表達了 UX 中的連接,所以我們就:
趕快來試試,哈哈哈,很好玩,而且各位一定要把 devTools 中的慢動作打開,這樣就可以看到 Flutter 是怎麼自動將你的 Hero Widget 用動畫連接了。
Hero 基本上只能動畫連接相同的 Widget,各位如果不信邪,可以把「終點」換一個大一點的 Widget,很快你就會看到類似 RenderFlex overflowed by xx pixels 的錯誤,也就是告訴你說,你的圖太大了,動畫越界了,好啦,我們只是先體驗一下 Flutter 的動畫,以後的章節會有詳細的用法與說明。
好啦,我們現在知道怎麼在 Flutter 的 navigator 中傳送資料了。
最後的程式碼,請自行參考本書:程式碼備份中的 Code milestone 2。