<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                在上一篇文章中,我帶你一起學習了如何在 Flutter 中實現跨組件數據傳遞。其中,InheritedWidget 適用于子 Widget 跨層共享父 Widget 數據的場景,如果子 Widget 還需要修改父 Widget 數據,則需要和 State 一起配套使用。而 Notification,則適用于父 Widget 監聽子 Widget 事件的場景。對于沒有父子關系的通信雙方,我們還可以使用 EventBus 實現基于訂閱 / 發布模式的機制實現數據交互。 如果說 UI 框架的視圖元素的基本單位是組件,那應用程序的基本單位就是頁面了。對于擁有多個頁面的應用程序而言,如何從一個頁面平滑地過渡到另一個頁面,我們需要有一個統一的機制來管理頁面之間的跳轉,通常被稱為**路由管理或導航管理**。 我們首先需要知道目標頁面對象,在完成目標頁面初始化后,用框架提供的方式打開它。比如,在 Android/iOS 中我們通常會初始化一個 Intent 或 ViewController,通過 startActivity 或 pushViewController 來打開一個新的頁面;而在 React 中,我們使用 navigation 來管理所有頁面,只要知道頁面的名稱,就可以立即導航到這個頁面。 其實,Flutter 的路由管理也借鑒了這兩種設計思路。那么,今天我們就來看看,如何在一個 Flutter 應用中管理不同頁面的命名和過渡。 ## 路由管理 在 Flutter 中,頁面之間的跳轉是通過 Route 和 Navigator 來管理的: * Route 是頁面的抽象,主要負責創建對應的界面,接收參數,響應 Navigator 打開和關閉; * 而 Navigator 則會維護一個路由棧管理 Route,Route 打開即入棧,Route 關閉即出棧,還可以直接替換棧內的某一個 Route。 而根據是否需要提前注冊頁面標識符,Flutter 中的路由管理可以分為兩種方式: * 基本路由。無需提前注冊,在頁面切換時需要自己構造頁面實例。 * 命名路由。需要提前注冊頁面標識符,在頁面切換時通過標識符直接打開新的路由。 接下來,我們先一起看看基本路由這種管理方式吧。 ### 基本路由 在 Flutter 中,**基本路由的使用方法和 Android/iOS 打開新頁面的方式非常相似**。要導航到一個新的頁面,我們需要創建一個 MaterialPageRoute 的實例,調用 Navigator.push 方法將新頁面壓到堆棧的頂部。 其中,MaterialPageRoute 是一種路由模板,定義了路由創建及切換過渡動畫的相關配置,可以針對不同平臺,實現與平臺頁面切換動畫風格一致的路由切換動畫。 而如果我們想返回上一個頁面,則需要調用 Navigator.pop 方法從堆棧中刪除這個頁面。 下面的代碼演示了基本路由的使用方法:在第一個頁面的按鈕事件中打開第二個頁面,并在第二個頁面的按鈕事件中回退到第一個頁面: ~~~ class FirstScreen extends StatelessWidget { @override Widget build(BuildContext context) { return RaisedButton( // 打開頁面 onPressed: ()=> Navigator.push(context, MaterialPageRoute(builder: (context) => SecondScreen())); ); } } class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return RaisedButton( // 回退頁面 onPressed: ()=> Navigator.pop(context) ); } } ~~~ 運行一下代碼,效果如下: :-: ![](https://img.kancloud.cn/18/95/18956211d36dffacea40592a2cc9cd10_636x1136.gif) 圖 1 基本路由示例 可以看到,基本路由的使用還是比較簡單的。接下來,我們再看看命名路由的使用方法。 ### 命名路由 基本路由使用方式相對簡單靈活,適用于應用中頁面不多的場景。而在應用中頁面比較多的情況下,再使用基本路由方式,那么每次跳轉到一個新的頁面,我們都要手動創建 MaterialPageRoute 實例,初始化頁面,然后調用 push 方法打開它,還是比較麻煩的。 所以,Flutter 提供了另外一種方式來簡化路由管理,即命名路由。我們給頁面起一個名字,然后就可以直接通過頁面名字打開它了。這種方式簡單直觀,**與 React 中的 navigation 使用方式類似**。 要想通過名字來指定頁面切換,我們必須先給應用程序 MaterialApp 提供一個頁面名稱映射規則,即路由表 routes,這樣 Flutter 才知道名字與頁面 Widget 的對應關系。 路由表實際上是一個 Map,其中 key 值對應頁面名字,而 value 值則是一個 WidgetBuilder 回調函數,我們需要在這個函數中創建對應的頁面。而一旦在路由表中定義好了頁面名字,我們就可以使用 Navigator.pushNamed 來打開頁面了。 下面的代碼演示了命名路由的使用方法:在 MaterialApp 完成了頁面的名字 second\_page 及頁面的初始化方法注冊綁定,后續我們就可以在代碼中以 second\_page 這個名字打開頁面了: ~~~ MaterialApp( ... // 注冊路由 routes:{ "second_page":(context)=>SecondPage(), }, ); // 使用名字打開頁面 Navigator.pushNamed(context,"second_page"); ~~~ 可以看到,命名路由的使用也很簡單。 不過**由于路由的注冊和使用都采用字符串來標識,這就會帶來一個隱患**:如果我們打開了一個不存在的路由會怎么辦? 也許你會想到,我們可以約定使用字符串常量去定義、使用路由,但我們無法避免通過接口數據下發的錯誤路由標識符場景。面對這種情況,無論是直接報錯或是不響應錯誤路由,都不是一個用戶體驗良好的解決辦法。 **更好的辦法是**,對用戶進行友好的錯誤提示,比如跳轉到一個統一的 NotFoundScreen 頁面,也方便我們對這類錯誤進行統一收集、上報。 在注冊路由表時,Flutter 提供了 UnknownRoute 屬性,我們可以對未知的路由標識符進行統一的頁面跳轉處理。 下面的代碼演示了如何注冊錯誤路由處理。和基本路由的使用方法類似,我們只需要返回一個固定的頁面即可。 ~~~ MaterialApp( ... // 注冊路由 routes:{ "second_page":(context)=>SecondPage(), }, // 錯誤路由處理,統一返回 UnknownPage onUnknownRoute: (RouteSettings setting) => MaterialPageRoute(builder: (context) => UnknownPage()), ); // 使用錯誤名字打開頁面 Navigator.pushNamed(context,"unknown_page"); ~~~ 運行一下代碼,可以看到,我們的應用不僅可以處理正確的頁面路由標識,對錯誤的頁面路由標識符也可以統一跳轉到固定的錯誤處理頁面了。 :-: ![](https://img.kancloud.cn/dc/00/dc007d9b1313c88a22aa27b3e1f5a897_636x1136.gif) 圖 2 命名路由示例 ### 頁面參數 與基本路由能夠精確地控制目標頁面初始化方式不同,命名路由只能通過字符串名字來初始化固定目標頁面。為了解決不同場景下目標頁面的初始化需求,Flutter 提供了路由參數的機制,可以在打開路由時傳遞相關參數,在目標頁面通過 RouteSettings 來獲取頁面參數。 下面的代碼演示了如何傳遞并獲取參數:使用頁面名稱 second\_page 打開頁面時,傳遞了一個字符串參數,隨后在 SecondPage 中,我們取出了這個參數,并將它展示在了文本中。 ~~~ // 打開頁面時傳遞字符串參數 Navigator.of(context).pushNamed("second_page", arguments: "Hey"); class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { // 取出路由參數 String msg = ModalRoute.of(context).settings.arguments as String; return Text(msg); } } ~~~ 除了頁面打開時需要傳遞參數,對于特定的頁面,在其關閉時,也需要傳遞參數告知頁面處理結果。 比如在電商場景下,我們會在用戶把商品加入購物車時,打開登錄頁面讓用戶登錄,而在登錄操作完成之后,關閉登錄頁面返回到當前頁面時,登錄頁面會告訴當前頁面新的用戶身份,當前頁面則會用新的用戶身份刷新頁面。 與 Android 提供的 startActivityForResult 方法可以監聽目標頁面的處理結果類似,Flutter 也提供了**返回參數**的機制。在 push 目標頁面時,可以設置目標頁面關閉時監聽函數,以獲取返回參數;而目標頁面可以在關閉路由時傳遞相關參數。 下面的代碼演示了如何獲取參數:在 SecondPage 頁面關閉時,傳遞了一個字符串參數,隨后在上一頁監聽函數中,我們取出了這個參數,并將它展示了出來。 ~~~ class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Column( children: <Widget>[ Text('Message from first screen: $msg'), RaisedButton( child: Text('back'), // 頁面關閉時傳遞參數 onPressed: ()=> Navigator.pop(context,"Hi") ) ] )); } } class _FirstPageState extends State<FirstPage> { String _msg=''; @override Widget build(BuildContext context) { return new Scaffold( body: Column(children: <Widget>[ RaisedButton( child: Text('命名路由(參數 & 回調)'), // 打開頁面,并監聽頁面關閉時傳遞的參數 onPressed: ()=> Navigator.pushNamed(context, "third_page",arguments: "Hey").then((msg)=>setState(()=>_msg=msg)), ), Text('Message from Second screen: $_msg'), ],), ); } } ~~~ 運行一下,可以看到在關閉 SecondPage,重新回到 FirstPage 頁面時,FirstPage 把接收到的 msg 參數展示了出來: :-: ![](https://img.kancloud.cn/df/b1/dfb17d88a9755a0a8bafde69ff1df090_748x1336.gif) 圖 3 頁面路由參數 ## 總結 好了,今天的分享就到這里。我們簡單回顧一下今天的主要內容吧。 Flutter 提供了基本路由和命名路由兩種方式,來管理頁面間的跳轉。其中,基本路由需要自己手動創建頁面實例,通過 Navigator.push 完成頁面跳轉;而命名路由需要提前注冊頁面標識符和頁面創建方法,通過 Navigator.pushNamed 傳入標識符實現頁面跳轉。 對于命名路由,如果我們需要響應錯誤路由標識符,還需要一并注冊 UnknownRoute。為了精細化控制路由切換,Flutter 提供了頁面打開與頁面關閉的參數機制,我們可以在頁面創建和目標頁面關閉時,取出相應的參數。 可以看到,關于路由導航,Flutter 綜合了 Android、iOS 和 React 的特點,簡潔而不失強大。 而在中大型應用中,我們通常會使用命名路由來管理頁面間的切換。命名路由的最重要作用,就是建立了字符串標識符與各個頁面之間的映射關系,使得各個頁面之間完全解耦,應用內頁面的切換只需要通過一個字符串標識符就可以搞定,為后期模塊化打好基礎。 我把今天分享所涉及的的知識點打包到了[GitHub](https://github.com/cyndibaby905/21_router_demo)上,你可以下載工程到本地,多運行幾次,從而加深對基本路由、命名路由以及路由參數具體用法的印象。 ## 思考題 最后,我給你留下兩個小作業吧。 1. 對于基本路由,如何傳遞頁面參數? 2. 請實現一個計算頁面,這個頁面可以對前一個頁面傳入的 2 個數值參數進行求和,并在該頁面關閉時告知上一頁面計算的結果。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看