Flutter入門進(jìn)階之旅(十三)Flutter 路由

Flutter路由介紹

跟Web頁或者原生APP一樣,我們?cè)谑褂肍lutter 開發(fā)APP時(shí)也會(huì)涉及到多頁面之間的跳轉(zhuǎn)、參數(shù)傳遞、參數(shù)回傳等業(yè)務(wù),Flutter路由能滿足上述我們提到的所有業(yè)務(wù)類型,此外我們也可以結(jié)合Flutter動(dòng)畫給路由跳頁時(shí)添加個(gè)性化的跳頁動(dòng)畫操作,我會(huì)在后續(xù)Flutter動(dòng)畫章節(jié)中具體講解。通過本節(jié)專題,讀者不僅僅可以自己動(dòng)手做一些簡單的UI,還能利用Fluttter 路由結(jié)合之前的課程分享做一些簡單的多頁面Flutter App。

本期課程目標(biāo)
  • 了解并掌握Flutter路由的簡單使用
  • 掌握Flutter動(dòng)態(tài)路由跟靜態(tài)路由的區(qū)別
  • 掌握Flutter路由在頁面間的參數(shù)傳遞以及回傳流程
  • 借助路由結(jié)合之前的課程做一些簡單的多頁面Flutter APP

關(guān)于靜態(tài)路由跟動(dòng)態(tài)路由

在Flutter中路由分為靜態(tài)路由動(dòng)態(tài)路由兩種:Flutter中所謂的靜態(tài)路由指的是需要提前把各個(gè)需要跳轉(zhuǎn)的頁面路徑注冊(cè)在routes: <String, WidgetBuilder> {}中,且靜態(tài)路由不支持向下一個(gè)頁面?zhèn)鬟f參數(shù),但是可以接收下一個(gè)頁面的返回值
動(dòng)態(tài)路由使用就相對(duì)來說比較靈活一點(diǎn),動(dòng)態(tài)路由同樣支持向下一個(gè)頁面?zhèn)鬟f參數(shù),而且在使用時(shí)不需要我們提前規(guī)劃好頁面路徑,只需要在具體跳頁邏輯中自己去構(gòu)造MaterialPageRoute對(duì)象來完成頁面跳轉(zhuǎn),或者用PageRouterBuilder來自定義路由跳轉(zhuǎn)時(shí)的動(dòng)畫,關(guān)于路由跳轉(zhuǎn)動(dòng)畫我會(huì)在Flutter動(dòng)畫章節(jié)中具體講解,當(dāng)然動(dòng)態(tài)路由同樣也支持頁面參數(shù)回傳。

路由場景分類

1.靜態(tài)路由跳頁

場景一:點(diǎn)擊A頁面中的按鈕跳轉(zhuǎn)到B頁,不涉及到數(shù)據(jù)傳遞以及回傳

效果圖

靜態(tài)路由跳頁

靜態(tài)路由使用時(shí)要求我們?cè)?code>MaterialApp中的routes中提前注冊(cè)路由

new MaterialApp(
      home: new FlutterDemo(),
      routes: <String, WidgetBuilder>{
        'router/new_page': (_) => new StaticNavigatorPage()
      }));
      

A頁面代碼

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/StaticNavigatorPage.dart';

void main() {
  runApp(new MaterialApp(
      home: new FlutterDemo(),
      routes: <String, WidgetBuilder>{
        'router/new_page': (_) => new StaticNavigatorPage()
      }));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Flutter進(jìn)階之旅"),
      ),
      body: new Center(
          child: new RaisedButton(
              child: new Text("靜態(tài)路由跳頁"),
              onPressed: () {
                Navigator.of(context)
                    .pushNamed('router/new_page'); //這里一定要保證跳頁的路由路徑跟上面注冊(cè)的路徑一致
              })),
    );
  }
}

B頁面代碼

import 'package:flutter/material.dart';

class StaticNavigatorPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("靜態(tài)路由頁"),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          Navigator.of(context).pop();
        },
        child: new Text("返回"),
      ),
      body: new Center(
        child: Text("靜態(tài)路由可以傳入一個(gè)routes參數(shù)來定義路由。但是這里定義的路由是靜態(tài)的,"
            "它不可以向下一個(gè)頁面?zhèn)鬟f參數(shù),利用push到一個(gè)新頁面,pushNamed方法是有一個(gè)Future的返回值的"
            ",所以靜態(tài)路由也是可以接收下一個(gè)頁面的返回值的。但是不能向下一個(gè)頁面?zhèn)鬟f參數(shù)"),
      ),
    );
  }
}

上述借助路由跳頁過程中我們注意到,大概分以下幾步:
1.注冊(cè)路由且保證路由的唯一性
2.跳頁時(shí)使用Navigator.of(context).pushNamed('路由地址');
3.使用Navigator.of(context).pop();結(jié)束當(dāng)前頁

2.靜態(tài)路由跳頁接收下一頁的返回值

場景二:點(diǎn)擊A頁面上的按鈕跳頁到B頁面,在B頁面銷毀后A頁面接收到B頁面回傳回來的值并且顯示在AlertDialog

效果圖

靜態(tài)路由回傳數(shù)據(jù)

A頁面代碼:
使用Navigator push一個(gè)新頁面,pushNamed方法是有一個(gè)Future的返回值的,在then回調(diào)中監(jiān)聽并接收新頁面回傳回來的數(shù)據(jù),并且借助showDialog顯示在Dialog

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/StaticNavigatorPageWithParams.dart';

void main() {
  runApp(
      new MaterialApp(home: new FlutterDemo(), routes: <String, WidgetBuilder>{
    'router/new_page_with_callback': (_) => new StaticNavigatorPageWithResult()
  }));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Flutter進(jìn)階之旅"),
      ),
      body: new Center(
          child: new RaisedButton(
              child: new Text("靜態(tài)路由接收下一頁返回值"),
              onPressed: () {
                Navigator.of(context)
                    .pushNamed('router/new_page_with_callback')
                    .then((value) {
                  showDialog(
                      context: context,
                      child: new AlertDialog(
                        content: new Text(value),  
                      ));
                });
              })),
    );
  }
}

B頁面代碼:

從效果圖中可以看到,當(dāng)我點(diǎn)擊B頁面中間的按鈕時(shí)會(huì)把數(shù)據(jù)回傳給上一頁,但是直接點(diǎn)擊導(dǎo)航欄左上角的返回按鈕回到A頁面時(shí)并不會(huì)把數(shù)據(jù)傳遞給上一個(gè)頁面,這里是因?yàn)槲以贐頁面的按鈕上pop頁面出棧的時(shí)候把參數(shù)放進(jìn)里面作為了參數(shù)傳遞,pop()可接收一個(gè)Object對(duì)象作為參數(shù)傳遞

Navigator.of(context).pop(T extends Object);

這就告訴我們當(dāng)我們需要給上一個(gè)頁面回傳數(shù)據(jù)的時(shí)候可直接借助pop傳遞Navigator.of(context).pop("頁面結(jié)束后返回的數(shù)據(jù)");,不需要傳值的時(shí)候直接返回空對(duì)象Navigator.of(context).pop()即可。

import 'package:flutter/material.dart';

class StaticNavigatorPageWithResult extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("靜態(tài)路由帶返回參數(shù)"),
      ),
      body: new Center(
        child: new OutlineButton(
          onPressed: () {
            Navigator.of(context).pop("頁面結(jié)束后返回的數(shù)據(jù)");
          },
          child: Text("點(diǎn)我返回上個(gè)頁面結(jié)束后返回的數(shù)據(jù)"),
        ),
      ),
    );
  }
}

3.動(dòng)態(tài)路由跳頁

文章的開頭我們提到借助動(dòng)態(tài)路由可以向下一個(gè)頁面?zhèn)鬟f參數(shù),同樣也可以接收新頁面回傳回來的數(shù)據(jù)。下面我模擬兩個(gè)使用動(dòng)態(tài)路由的場景,既然動(dòng)態(tài)路由可以傳值那就肯定可以不傳值跳頁,我就不模擬動(dòng)態(tài)路由不傳值跳頁的例子了,讀者借助靜態(tài)路由的樣例自行測試即可,我們主要講解一下借助動(dòng)態(tài)路由傳值的例子。

場景三:點(diǎn)擊A頁面中的按鈕,把用戶名跟密碼傳遞給下一個(gè)頁面B頁面,B頁面處理完接收到的數(shù)據(jù)后把結(jié)果回傳給A頁面,A頁面中把從B頁面回傳回來的數(shù)據(jù)顯示在Dialog上。

模擬效果圖

動(dòng)態(tài)路由傳遞參數(shù)

使用動(dòng)態(tài)路由時(shí)我們不再需要像靜態(tài)路由那樣在MaterialApp中的router中提前注冊(cè)路由路徑,只需要在使用Navigator.push傳入MaterialPageRoute對(duì)象即可

 Navigator.push(
    context,
    new MaterialPageRoute(
        //_代表參數(shù)為空
        builder: (_) => new DynamicNaviattionPage(
              username: "xiedong",
              password: "123456",
            )));

A頁面代碼:

import 'package:flutter/material.dart';
import 'package:flutter_app/pages/simpleWidget/navigator/DynamicNavigationPage.dart';

void main() {
  runApp(new MaterialApp(home: new FlutterDemo()));
}

class FlutterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Flutter進(jìn)階之旅"),
        ),
        body: new Center(
            child: new RaisedButton(
          onPressed: () {
            Navigator.push(
                context,
                new MaterialPageRoute(
                    //_代表參數(shù)為空
                    builder: (_) => new DynamicNaviattionPage(
                          username: "xiedong",
                          password: "123456",
                        ))).then((value) {
              showDialog(
                  context: context,
                  child: new AlertDialog(
                    content: new Text(value),
                  ));
            });
          },
          child: new Text("動(dòng)態(tài)路由傳參"),
        )));
  }
}

B頁面代碼:

import 'package:flutter/material.dart';

class DynamicNaviattionPage extends StatelessWidget {
  var username;
  var password;

  DynamicNaviattionPage({Key key, this.username, this.password})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("動(dòng)態(tài)路由"),
      ),
      body: new Center(
        child: new Column(
          children: <Widget>[
            new MaterialButton(
              onPressed: () {
                Navigator.pop(context, "未查詢到改該用戶信息");
              },
              child: new Text("點(diǎn)我返回"),
              color: Colors.lightGreen,
            ),
            new Text("上頁傳遞過來的username   $username"),
            new Text("上頁傳遞過來的password   $password"),
          ],
        ),
      ),
    );
  }
}

關(guān)于路由重點(diǎn)總結(jié)

  • Flutter路由分為靜態(tài)路由跟動(dòng)態(tài)路由,靜態(tài)路由不支持向下一個(gè)頁面?zhèn)鬟f參數(shù),動(dòng)態(tài)路由可傳遞
  • 靜態(tài)路由使用時(shí)需要提前注冊(cè)聲明頁面路徑,
  • 動(dòng)態(tài)路由可以直接在使用時(shí)構(gòu)造路由對(duì)象,不需要提前注冊(cè)路徑。
  • 兩種類型都支持接收下一頁面回傳回來的值

下一篇:Flutter入門進(jìn)階之旅(十四)ListView&GridView

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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