Flutter路由&pop()&Push()全面解析

[TOC]

前言

Route (路由)
Router (路由管理器)
將一個(gè)URL路徑和一個(gè)函數(shù)映射

/users -> getAllUsers()
/users/count -> getUsersCount()

或者將一個(gè)頁面和方法映射

  getHome()=> homePage.index

在Flutter中是將一個(gè)字符串和一個(gè)方法(或者說page)映射

"homePage" -> new HomePage()

靜態(tài)路由

靜態(tài)路由就是通過字符串進(jìn)行注冊的路由

return new MaterialApp(
     title: 'Flutter Demo',
     theme: new ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: new MyHomePage(title: 'Flutter實(shí)例'),
     routes: <String, WidgetBuilder> {
       // 這里可以定義靜態(tài)路由,不能傳遞參數(shù)
       '/router/second': (_) => new SecondPage(),
       '/router/home': (_) => new RouterHomePage(),
     },
   );

使用
push一個(gè)新頁面,pushNamed方法是有一個(gè)Future的返回值的,所以靜態(tài)路由也是可以接收下一個(gè)頁面的返回值的。但是不能向下一個(gè)頁面?zhèn)鬟f參數(shù)。

Navigator.of(context).pushNamed('/router/second');

// 帶返回值

Navigator.of(context).pushNamed('/router/second').then((value) {
                    // dialog顯示返回值
                    _showDialog(context, value);
                  })

pop回上一個(gè)頁面
Navigator.of(context).pop('這個(gè)是要返回給上一個(gè)頁面的數(shù)據(jù)');

動(dòng)態(tài)路由的使用

當(dāng)需要向下一個(gè)頁面?zhèn)鬟f參數(shù)時(shí),要用到所謂的動(dòng)態(tài)路由,自己生成頁面對象,所以可以傳遞自己想要的參數(shù)。

Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
                    return new SecondPage(title: '路由是個(gè)好東西,要進(jìn)一步封裝');
                  }));

也可以用PageRouterBuilder來自定義打開動(dòng)畫

Navigator.of(context).push(new PageRouteBuilder(pageBuilder:
            (BuildContext context, Animation<double> animation,
                Animation<double> secondaryAnimation) {
          return new RefreshIndicatorDemo();
        }, transitionsBuilder: (
          BuildContext context,
          Animation<double> animation,
          Animation<double> secondaryAnimation,
          Widget child,
        ) {
          // 添加一個(gè)平移動(dòng)畫
          return BRouter.createTransition(animation, child);
        }));

平移的變換
/// 創(chuàng)建一個(gè)平移變換
/// 跳轉(zhuǎn)過去查看源代碼,可以看到有各種各樣定義好的變換

  static SlideTransition createTransition(
      Animation<double> animation, Widget child) {
    return new SlideTransition(
      position: new Tween<Offset>(
        begin: const Offset(1.0, 0.0),
        end: const Offset(0.0, 0.0),
      ).animate(animation),
      child: child, // child is the value returned by pageBuilder
    );
  }

Page(控制器)的入棧和出棧和刷新。

 以下是Flutter出棧和入棧的方法,共計(jì)13種,當(dāng)然也有直接是Navigator.push 之類的對照方法共計(jì)13種,他們沒什么區(qū)別,
 因?yàn)镹avigator.method()這些方法其實(shí)也是調(diào)用下面的方法實(shí)現(xiàn)的。

 ********************

 Navigator.of(context).pushReplacement(newRoute);
 Navigator.of(context).push(route);
 Navigator.of(context).pushReplacementNamed(routeName);
 Navigator.of(context).pushNamed(routeName);
 Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, predicate)
 
 Navigator.of(context).pop();
 Navigator.of(context).popAndPushNamed(routeName);
 Navigator.of(context).popUntil(predicate);
 Navigator.of(context).maybePop();

 Navigator.of(context).removeRouteBelow(anchorRoute);
 Navigator.of(context).removeRoute(route);

 Navigator.of(context).replace(oldRoute: null, newRoute: null);
 Navigator.of(context).replaceRouteBelow(anchorRoute: null);
Navigator.of(context).push();
 官方的給的demo
 Navigator.push(context, 
MaterialPageRoute(builder: (BuildContext context) => MyPage()));
 1、適用非靜態(tài)路由進(jìn)行跳轉(zhuǎn)。
 2、傳遞參數(shù)只能通過控制器的構(gòu)造進(jìn)行傳遞。
Navigator.of(context).pushNamed(context,routeName,args)
類似上面的push方法,不過只能打開靜態(tài)Route,可以通過args傳遞參數(shù)。
D7F05CA1-3770-4CD9-A1CA-A666D92A4740.png
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, predicate)
87D3DCF4-60EC-4A38-9C3F-4C353BFA6807.png
 flutter 默認(rèn)有兩種路由(靜態(tài)路由和動(dòng)態(tài)路由)
 對應(yīng)的RouterName也有兩種方式進(jìn)行申明,
  * 靜態(tài)路由在注冊的時(shí)候就進(jìn)行了申明,默認(rèn)MainPager 為(“/”)
  * 動(dòng)態(tài)路由是當(dāng)你打開這個(gè)Route的進(jìn)行設(shè)置的(RouteSettings.name="pagerName")
  
  
  上面圖示采用以下方式就行打開頁面
  Navigator.pushAndRemoveUntil(context,
                MaterialPageRoute(builder: (BuildContext context) {
              return CPager();
            }), ModalRoute.withName("pagerA"));
            
  1 :左1為操作流程,左二為結(jié)果:可以發(fā)現(xiàn)  A_Pager&B_Pager都被結(jié)束掉了,直到碰到MainPage 也就是默認(rèn)routName為"/"的主界面。
  
  2 :右2為操作流程,右1為結(jié)果, B-Pager被結(jié)束掉了,知道碰到的routeName為pageA的界面。
  
  所以這個(gè)push方法的作用就是打開一個(gè)新界面,并且結(jié)束掉之后的界面,直到碰到指定RoutName的Pager為止,如果一個(gè)都沒有匹配到,就會(huì)結(jié)束所有pager除了新打開的這個(gè)Pager.
Navigator.of(context).pushReplacement(newRoute,To result)
F55C7B67-C326-4417-AA65-DDCD619A0F73.png
!、pushReplacement 這個(gè)很好理解,就是Push的Pager替換當(dāng)前Pager,可以是新的界面,也可以是刷新當(dāng)前界面。

 注意這里的To result 其實(shí)這個(gè)意思就是返回給上一個(gè)route(當(dāng)前正被替換的route的開啟者)的一個(gè)結(jié)果,官網(wǎng)文檔表明這是為了彈出框或者選擇框被消失,并進(jìn)入下一個(gè)界面,需要將結(jié)果返回上一個(gè)界面可以進(jìn)行的操作。
 
 
 
 If non-null, `result` will be used as the result of the route that is
 popped; the future that had been returned from pushing the popped route
 will complete with `result`. Routes such as dialogs or popup menus
 typically use this mechanism to return the value selected by the user to
 the widget that created their route. The type of `result`, if provided,
 must match the type argument of the class of the popped route (`TO`).

Navigator.pop(context)
關(guān)閉一個(gè)路由,這里可以是Route也可以是Dialog, pop都是可以向上一層返回?cái)?shù)據(jù)的。
Navigator.of(context).popAndPushNamed(routeName);
Navigator.of(context).popUntil(predicate);
 參考以上push
Navigator.of(context).mayPop(content);
 這個(gè)Android 開發(fā)者很好理解,這個(gè)就是喚醒了一個(gè)Android返回物理鍵,如果當(dāng)前route 沒有WillPopScope()進(jìn)行包裹(也即是攔截物理返回鍵&navigatorBar返回鍵),他就結(jié)束當(dāng)前route。如果進(jìn)行了包裹,就不結(jié)束當(dāng)前界面。
Navigator.of(context).removeRouteBelow(anchorRoute);
Navigator.of(context).removeRoute(route);
 這個(gè)兩個(gè)一般用不到,官方說法
 removeRoute:
 This method is used, for example, to instantly dismiss dropdown menus that
 are up when the screen's orientation changes.
 
 也就是說移除當(dāng)前Route上的彈出框,我測試的時(shí)候,是用EvenBus方法在B-Pager中點(diǎn)擊觸發(fā)event,在A-Pager中移除了B-Pager,其實(shí)這個(gè)用到的地方就是你必須持有對應(yīng)要移除的路由Instant.
 removeRouteBelow: 就是移除指定路由底層的臨近的一個(gè)路由,當(dāng)對應(yīng)路由不存在的時(shí)候會(huì)報(bào)錯(cuò)。
Navigator.replace(context, oldRoute: null, newRoute: null)
Navigator.replaceRouteBelow();
 這個(gè)兩個(gè)方法也必須持有oldRoute的Instant,目的就是替換對應(yīng)的路由。
 官方說法是為了構(gòu)建非線型用戶體驗(yàn),這個(gè)說法就是針對線型Android開發(fā)人員熟悉的APager->BPager->CPager 
然后返回就是 CPager->BPager->APager
通常之前Android面試:會(huì)問到你一個(gè)常見的問題,如果控制幾個(gè)Activty流程用來達(dá)到業(yè)務(wù)流程的目的,用上Flutter 你會(huì)發(fā)現(xiàn)這些很簡單就能實(shí)現(xiàn)了,而不必要進(jìn)行維護(hù)一個(gè)ActivityStack,或者通過Actity生命周期進(jìn)行攔截的復(fù)雜方式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容