FlutterのNavigator2.0をちょっと調べる
Flutter1.22からNavigator2.0が導入されたのでちょっと調べてみる。
Navigator1.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])); } }
- onGeneratedRoute: 上述のnamed routesだと静的にrouteを定義することしか出来ないので
-
Navigator2.0
Navigator1.0とくらべてNavigator2.0では宣言的に書けるようになった。
- Page: Routeに関する設定情報を保持するオブジェクト
- Router: Navigatorのラッパー
- RouteInformationParser:
RouteInformationProvider
から受け取ったRouteInformation
を元にurlをパースをする - RouterDelegate:
State
とRouteInformationParser
の変化をlistenしてWidget(Navigator)のbuildを実行する。変化ごとにrebuildするお仕事。
- RouteInformationParser:
Navigator1.0のonGeneratedRoute
ではurlのパースと各ページへの遷移が合わせて手続き的に書かれる。Navigator2.0ではPage
とRouter
を導入することでそうしたパースの処理やページへの遷移を分割して宣言的に書くことができるようになった。
ただ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
そんで、このgistをlib/main.dart
に貼り付けてflutter run -d chrome
を実行すれば挙動が確認できるはず。master channelじゃないとurlのpathに直接アクセスしてページが切り替わる機能は使えないので注意。
Discussion