最近開發的Flutter項目有個需求:app有個頁面是綁定卡片,要求綁卡成功后退回查詢頁面,查詢頁面與綁卡頁面之間有一個頁面。
經過簡單查詢,發現很多技術博客都是介紹的pushReplacement和pushAndRemoveUntil這兩個方法,但是根據這些博客給出的案例無法實現我的需求,於是我只好去看官方文檔。
對於pushReplacement,官方文檔的描述如下:Replace the current route of the navigator that most tightly encloses the given context by pushing the given route and then disposing the previous route once the new route has finished animating in.
大概意思是在路由棧中把當前路由的記錄換成一個新的路由的記錄,具體操作為在新路由入棧后銷毀之前的路由。
對於pushAndRemoveUntil,官方文檔的描述如下:Push the given route onto the navigator that most tightly encloses the given context, and then remove all the previous routes until the predicate returns true.
大概意思是入棧一個新路由,然后把棧中其他路由全部清除,直到判定條件返回true。
我目前的需求是從頁面1進入頁面2,再從頁面2進入頁面3,然后操作成功返回頁面1。路由棧中在返回頁面1之前應該是[頁面1,頁面2,頁面3],我需要的效果為在操作成功后路由棧變為[[頁面1]。
如果我選擇pushReplacement,那么路由棧會變成[頁面1,頁面2,頁面1],跟我的需求不符。我也沒有選擇pushAndRemoveUntil,一開始我就沒選擇這個方法,因為我粗略一看認為它無法實現,但是在寫這篇文章的時候,我突然想到按照邏輯他應該是可以實現的,於是我進行了測試,按照文檔的描述傳入2個參數,第一個參數是頁面1的路由,第二個參數是判定條件為頁面0時返回true。這里有一個問題就是這個判定條件應該怎么寫,其實它跟第三個方法一樣:它應該是一個返回bool值的函數-->bool Function(Route<dynamic> route)。
很多博客都是用的這樣的方法:ModalRoute.withName("home"),但是我的這個項目沒有使用命名路由,沒辦法使用這樣的語句。於是我試過自己判斷 route == MaterialPageRoute(builder:(context){return Home()}),事實證明這樣是不行的,因為路由是引用類型,他們兩個根本不會相等。最終我在stackoverflow上找到了解決方法:
Navigator.push( context, MaterialPageRoute( settings: RouteSettings(name: "Foo"), builder: ..., ), ); ------------ Navigator.pushAndRemoveUntil(newRoute, ModalRoute.withName("Foo"))
意思是在路由入棧的時候可以給它設置一個名字,這樣就算沒有使用命名路由系統,可以獲取路由的名字。
第三個方法是我原本最終采用的方法:
Navigator.push( context, MaterialPageRoute( settings: RouteSettings(name: "Foo"), builder: ..., ), ); ---------------- Navigator.popUntil(context, ModalRoute.withName("Foo"))
使用的是popUntil 方法,作用是一直把路由棧中的路由移除出棧,直到判定條件為true。
