🤔

flutterの画面遷移(ルーティング)でnavigatorとgorouterどちらを使うか

2024/05/14に公開

はじめに

flutterにおける画面遷移でnavigatorとgorouterのどちらを採用するか悩みました。
簡単なアプリでNavigator1.0、比較的複雑なアプリでgo_routerを使ってみたので実際のコードや参考を含めて記載しておきます。

バージョン

Flutter: 3.16.8
Dart: 3.2.5
go_router: 13.2.0

結論

  • 小規模な個人開発やテスト用のローカルリポジトリであればNavigator 1.0
  • WebViewを使用するのであればNavigator 2.0
  • チーム開発やViewの多いアプリではgo_router
  • コードが端的で書きやすい
  • 定義されているclassのため、パッケージを入れる必要がない
  • UIや機能のテストに便利
  • 静的、動的な細かい遷移を指定できる。
  • 定義されているclassのため、パッケージを入れる必要がない

go_routerのメリット

  • modelが1つあれば、各Viewページにて処理を簡単に実装できる
  • 実装内容としては、Navigator 2.0の仕様を踏襲

https://api.flutter.dev/flutter/widgets/Navigator-class.html

1. 新しい画面に遷移する(Push)

画面Aから画面Bへ遷移する場合、Navigator.pushメソッドを使用します。この方法は、新しい画面を画面スタックの上に積む操作に相当します。

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => NewScreen()), // NewScreenは遷移先の画面クラス
);

2. 画面を戻る(Pop)

画面Bから画面Aに戻る場合(または現在の画面を閉じる場合)、Navigator.popメソッドを使用します。

Navigator.pop(context);

3. 名前付きルートを使用する

Flutterでは、画面遷移を管理するために名前付きルート(Named Routes)を使用することができます。この方法では、アプリケーションのMaterialAppウィジェット内でルートを定義し、画面遷移時にその名前を指定します。

MaterialAppウィジェットでルートを定義する:

MaterialApp(
  // 名前付きルートの定義
  routes: {
    '/': (context) => HomeScreen(),
    '/new': (context) => NewScreen(),
  },
);

名前付きルートを使用して新しい画面に遷移する:

Navigator.pushNamed(context, '/new');

4. 引数を渡しながらの画面遷移

画面遷移する際に、次の画面にデータを渡すこともできます。MaterialPageRouteのbuilderプロパティに渡す関数で、データを引数にして新しい画面のインスタンスを作成します。

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => NewScreen(data: "データ"),
  ),
);

go_router

https://pub.dev/packages/go_router

go_routerの使い方

flutterのgo_routerで同様のことを書き直します。

1.まずはgo_routerパッケージをインポートします。

flutter pub add go_router
import 'package:go_router/go_router.dart';

Routerオブジェクトを生成します。

final router = Router();

ルートパス"/"にハンドラを登録します。

router.define(
  '/',
  handler: (BuildContext context, GoRouterState state) {
    return Text('Welcome'); 
  }
);

パスパラメーターを指定したルーティングです。

router.define(
  '/products/:key', 
  handler: (BuildContext context, GoRouterState state) {
    final key = state.params['key'];
    return Text('The key is $key');
  }
);

アプリ起動時にRouterを設定します。

void main() {
  runApp(
    MaterialApp.router(
      router: router
    )
  );
}

go_routerを使った複数ページのルーティング

ログインやBottoNavigationbarと組み合わせた際にやったこと

実際のアプリでの実装の際は、ログインやユーザーの動き次第での画面遷移、BottomNavgationbar、設定ページの中にネストされたページを一挙に実装した場合、以下の処理が必要になりました。

  • createRouterメソッドでGoRouterインスタンスを作成し、各ページルートを設定
  • ShellRouteでBottomNavWidgetをラップして子ルートとしてページを設定
  • 各ページ用のGoRouteを定義し、Builderでそれぞれのウィジェットを定義
  • AuthInfoModelからユーザー情報を見て初期ルートを決定
  • ログイン状態に応じてリダイレクト設定
  • 設定ページの下位ルートも定義

以下に1例として設定ページの中にネストしたページを入れて遷移させる場合のgo_router部分を抜粋します。

基本的な設定を行なった後、設定ページのルートを定義する

例えば、以下のように設定ページに入れる予定の3つのルート(画面遷移先)を書きます。
bottomnavigationbarにあるsetting(設定ページ)から遷移したいルートになります。

1.以下のようにそれぞれの遷移先ページを定義する(以下はプライバシーポリシーページ)

router
GoRoute privacyPolicyRoute() {
  return GoRoute(
    path: 'privacy_policy',
    builder: (context, state) {
      return const PrivacyPolicyPage();
    },
  );
}

2.設定ページからどこへ遷移するか定義する

router
GoRoute settingRoute() {
  return GoRoute(
    path: '/setting',
    routes: [
      languageSettingRoute(),//言語設定
      aboutAppRoute(),//アプリについての説明
      deleteAuthRoute(),//アカウント削除
    ],
    builder: (context, state) {
      return const SettingPage();//遷移先ページから設定ページに戻ることができる
    },
  );
}

3.さらにアプリについての説明ページから他ページへの遷移も定義する

router
GoRoute aboutAppRoute() {
  return GoRoute(
    path: 'about_app',
    routes: [
      kiyakuRoute(),
      termsOfServiceRoute(),
      privacyPolicyRoute(),
      developerInfoRoute(),
    ],
    builder: (context, state) {
      return const AboutAppPage();
    },
  );
}

今回参考にさせていただいた記事を以下に記載します。
読んでいただきありがとうございました。

参考

https://flutter.ctrnost.com/basic/routing/
https://zenn.dev/k_kawasaki/articles/2cee32fc8a907d
https://zenn.dev/koji_1009/articles/7b99e332c537cd
https://qiita.com/slime_a/items/7ae8143de189e446dd11

Discussion