go_router は、Googleが開発したパッケージで、シンプルで強力なルーティングシステムを提供し、Flutterアプリケーションの開発を効率的に進めるための優れたツールです。
特にURLベースのナビゲーションを必要とする場合や、Flutter Webとの統合を考慮する場合に非常に有用です。
1.サンプル(動作)
以下は、(前回記事と同じ仕様ですが)2つの画面(PageA画面(page_a.dart)、PageB画面(page_b.dart))を用意し、相互の画面遷移を行うサンプルです。
①PageA画面で、ElevatedButton「Go to PageB」をクリックします。
②するとPageB画面に遷移します。
ここで、ElevatedButton「Go to PageA」をクリックします。
③するとPageA画面に遷移し(戻り)ます。
2.サンプル(コード)
2ー1.ファイルの配置
各ファイルを以下の様に配置することとします。
lib/
├── main.dart
├── page_a.dart
└── page_b.dart
2ー2.各ファイルのコード
(1)main.dart
Dart
// main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; // go_routerパッケージをインポート
import 'page_a.dart'; // PageAを定義したファイルをインポート
import 'page_b.dart'; // PageBを定義したファイルをインポート
void main() {
runApp(MyApp()); // アプリケーションを実行するエントリーポイント
}
class MyApp extends StatelessWidget {
// GoRouterインスタンスを作成し、ルートを設定
final GoRouter _router = GoRouter(
// ルートの定義:
routes: [
// '/'パスに対応するウィジェットをPageAに設定
GoRoute(
path: '/',
builder: (context, state) => const PageA(),
),
// '/pageB'パスに対応するウィジェットをPageBに設定
GoRoute(
path: '/pageB',
builder: (context, state) => const PageB(),
),
],
);
MyApp({super.key});
@override
Widget build(BuildContext context) {
// MaterialApp.routerを使って、go_routerのルーティング機能を設定
return MaterialApp.router(
// ルーターのデリゲート
routerDelegate: _router.routerDelegate,
// ルート情報のパーサー
routeInformationParser: _router.routeInformationParser,
// ルート情報のプロバイダー
routeInformationProvider: _router.routeInformationProvider,
);
}
}
(2)page_a.dart
Dart
// page_a.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; // go_routerパッケージをインポート
class PageA extends StatelessWidget {
const PageA({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Page A')),
body: Center(
child: ElevatedButton(
onPressed: () {
context.go('/pageB'); // ボタンを押したときに、/pageBパスに遷移
},
child: const Text('Go to Page B'),
),
),
);
}
}
(3)page_b.dart
Dart
// page_b.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; // go_routerパッケージをインポート
class PageB extends StatelessWidget {
const PageB({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Page B')),
body: Center(
child: ElevatedButton(
onPressed: () {
context.go('/'); // ボタンを押したときに、/パスに遷移
},
child: const Text('Go to Page A'),
),
),
);
}
}
3.総括(処理の流れ)
上記の画面遷移処理は、以下の様な流れで処理されています。
(1) 初期画面の表示(main.dart → page_a.dart)
- アプリケーションが起動後、エントリーポイントが実行されます。
・runApp
関数が呼び出され、MyApp
ウィジェットがアプリケーションのルートとして設定されます。 MyApp
ウィジェットの構築
・MyApp
クラスのコンストラクタが呼び出され、GoRouter
インスタンスが作成されます。
このインスタンスは、アプリケーションのルートを管理します。
・GoRouter
のroutes
プロパティで、/
パスと/pageB
パスに対応する画面を設定します。
・MaterialApp.router
ウィジェットで、go_router
のルーティング機能をアプリケーションに組み込みます。
Dart
// main.dart
class MyApp extends StatelessWidget {
// GoRouterインスタンスを作成し、ルートを設定
<mark style="background-color:#fcb900" class="has-inline-color">final <strong>GoRouter</strong> _router = GoRouter(</mark>
// ルートの定義:
<mark style="background-color:#f78da7" class="has-inline-color"><strong>routes: [</strong></mark>
// '/'パスに対応するウィジェットをPageAに設定
<mark style="background-color:#f78da7" class="has-inline-color"><strong>GoRoute(</strong></mark>
<mark style="background-color:#f78da7" class="has-inline-color">path: '/',</mark>
builder: (context, state) => <strong><mark style="background-color:#f78da7" class="has-inline-color">const PageA()</mark></strong>,
),
// '/pageB'パスに対応するウィジェットをPageBに設定
<strong><mark style="background-color:#f78da7" class="has-inline-color">GoRoute(</mark></strong>
<mark style="background-color:#f78da7" class="has-inline-color">path: '/pageB',</mark>
builder: (context, state) => <strong><mark style="background-color:#f78da7" class="has-inline-color">const PageB()</mark></strong>,
),
<mark style="background-color:#f78da7" class="has-inline-color">],</mark>
<mark style="background-color:#fcb900" class="has-inline-color">);</mark>
- (上記により)
GoRouter
により初期ルートが評価され、/
パスに対応するPageA
が表示されます。
Dart
// page_a.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; // go_routerパッケージをインポート
class <strong><mark style="background-color:#fcb900" class="has-inline-color">PageA</mark></strong> extends StatelessWidget {
const PageA({super.key});
}
(2)画面遷移の実行(page_a.dart → page_b.dart)
- ユーザーがボタンを押すと、
context.go('/pageB')
が呼び出され、GoRouter
が/pageB
パスに対応する画面を表示します。
Dart
onPressed: () {
<strong><mark style="background-color:#fcb900" class="has-inline-color">context.go('/pageB');</mark></strong> // ページBへの遷移
}
(3)遷移後の画面の表示(page_b.dart)
/pageB
パスに対応するPageB
が表示されます。PageB
ウィジェットが表示され、ユーザーが操作できる状態になります。- ユーザーが「Go to Page A」ボタンを押すと、
context.go('/')
が呼び出されます。
Dart
// page_b.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; // go_routerパッケージをインポート
class PageB extends StatelessWidget {
const PageB({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Page B')),
body: Center(
child: ElevatedButton(
<mark style="background-color:#fcb900" class="has-inline-color">onPressed: () {</mark>
<mark style="background-color:#fcb900" class="has-inline-color">context.go('/');</mark> // ボタンを押したときに、/パスに遷移
<mark style="background-color:#fcb900" class="has-inline-color">},</mark>
child: const Text('Go to Page A'),
),
),
);
}
}
4.まとめ
- アプリケーション起動時に
main.dart
のmain
関数が実行され、MyApp
ウィジェットが表示される。 MyApp
ウィジェット内でGoRouter
が初期化され、ルート設定が行われる。- 初期画面として
PageA
が表示される。 - ユーザーが
PageA
のボタンを押すと、context.go('/pageB')
が呼び出され、PageB
に遷移する。 PageB
が表示され、ユーザーがPageB
のボタンを押すと、context.go('/')
が呼び出され、再びPageA
に遷移する。
この流れにより、go_router
を使ったシンプルな画面遷移の処理を理解できます。