🐬

FlutterのNavigator2.0をちょっと調べる

2020/10/06に公開

Flutter1.22からNavigator2.0が導入されたのでちょっと調べてみる。

まずはおさらい。従来のNavigator。Stackにrouteをpushしたりpopしたりするネイティブアプリなんかでは一般的な構造。登場人物としてはこんな感じ。

  • Navigator: RouteのStackを管理するやつ
  • Route: MaterialPageRouteのようなやつ。Navigatorで管理されるスクリーン。
    • anonymous routes: こんな感じで使うやつ。まさにページをStackに積んでいく。積まれてるrouteの状態はそれぞれ保持されてる。

      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) {
          return SampleScreen();
        })
      )
      
    • named routes: MaterialAppとかで事前に定義してNavigator.pushNamedを使い呼び出す感じのやつ。

      MaterialApp(
      routes:{
        '/': (context) => HomeScreen(),
        '/posts': (context) => PostsScreen(),
      })
      
      Navigator.pushNamed(
        context,
        '/posts',
      );
      
      • onGeneratedRoute: 上述のnamed routesだと静的にrouteを定義することしか出来ないので/posts/:idのようなrouteを定義できない。それを解決するためのやつ。
      // Navigator.pushNamedが呼ばれるとsettingsにRouteSettings情報が渡ってくる
      onGeneratedRoute: (settings) {
        if (settings.name == '/') {
          return MaterialPageRoute(builder: (context) => HomeScreen());
        }
        var uri = Uri.parse(settings.name);
        if (uri.pathSegments.length == 2 &&
          uri.pathSegments.first == 'posts') {
          return MaterialPageRoute(builder: (context) => PostScreen(id: uri.pathSegments[1]));
        }
      }
      

Navigator1.0とくらべてNavigator2.0では宣言的に書けるようになった。

  • Page: Routeに関する設定情報を保持するオブジェクト
  • Router: Navigatorのラッパー
    • RouteInformationParser: RouteInformationProviderから受け取ったRouteInformationを元にurlをパースをする
    • RouterDelegate: StateRouteInformationParserの変化をlistenしてWidget(Navigator)のbuildを実行する。変化ごとにrebuildするお仕事。

Navigator1.0のonGeneratedRouteではurlのパースと各ページへの遷移が合わせて手続き的に書かれる。Navigator2.0ではPageRouterを導入することでそうしたパースの処理やページへの遷移を分割して宣言的に書くことができるようになった。

ただNavigator1.0から2.0にマイグレーションして目に見えて嬉しいことがあるかと言われると自分はそんなにわからなかった...。webのルーティング周りを強化するためには必要な改善だったのかなと思うくらい。

実際に挙動を見てみる

とりあえずどんな挙動をするのか見てみたい場合はmaster channelの最新にupgradeして、ここを参考にweb supportをonにする。

$ flutter channel master
$ flutter upgrade
$ flutter config --enable-web
$ flutter create myapp
$ cd myapp

そんで、このgistlib/main.dartに貼り付けてflutter run -d chromeを実行すれば挙動が確認できるはず。master channelじゃないとurlのpathに直接アクセスしてページが切り替わる機能は使えないので注意。

リンク

Discussion