【Flutter】go_routerの基本とOSごとにテーマを分ける方法

こんにちは、エキサイトでアプリエンジニアをしている岡島です。エキサイトホールディングス Advent Calendar 2024の21日目を担当させていただきます。

今回はgo_routerを触ってみたので、go_routerについて共有していこうと思います。

環境

dependencies:
go_router: ^14.6.2

go_routerの特徴

go_routerは、ルーティングのライブラリであり、URLに基づいたナビゲーションのため、ディープリンクを扱いやすいなどの特徴があります。

pub.devのReadmeには次のような特徴があると書かれています。

  • テンプレート構文を使用したパス パラメーターとクエリ パラメーターの解析
  • 目的地(サブルート)の複数画面の表示
  • リダイレクトのサポート
  • ShellRouterによる複数のナビゲーターのサポート
  • MaterialとCupertinoアプリのサポート
  • Navigator API後方互換

go_routerの基本

準備

基本的に必要となることは以下のとおりです。

  1. GoRouterの構成を宣言する
  2. MaterialApp.routerCupertinoApp.routerを使用して準備をする

GoRouterの構成を宣言する

以下の例のようにそれぞれの画面を宣言していきます。

最低限必要なものはpathbuilderです。

final router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
    ),
    GoRoute(
      path: 'screen1',
      builder: (BuildContext context, GoRouterState state) {
        return const Screen1();
      },
    ),
  ],
);

はじめに開く画面を指定する場合はinitialLocationでパスを指定します。

final router = GoRouter(
  initialLocation: '/',
  routes: [
    // GoRoute()の宣言
  ],
);

他にもdebugLogDiagnostics: true, とするとログが出力されるようになります。

MaterialApp.routerやCupertinoApp.routerを使用して準備をする

アプリでgo_routerを利用するには、MaterialApp.routerCupertinoApp.router 使用し、routerConfig に宣言したGoRouterの構成オブジェクトを設定します。

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

以上で準備が完了です。

画面遷移の方法

ここまでの準備で、go_routerを利用すると、画面遷移の時にcontext.go()を用いて遷移することができます。下のように書くと、TextButtonをタップしてScreen1に遷移することができます。

  return TextButton(
    child: const Text('Screen1'),
    onPressed: () => context.go('/screen1'),
  );

他にもNavigator.of(context).push()Navigator.of(context).pop()の代わりにcontext.push()context.pop()が利用できます。

go_routerではBuildContextのナビゲーションに拡張関数を定義しています。

extension GoRouterHelper on BuildContext 

この拡張関数のおかげで、context.go()context.pop()というようにcontext.〇〇で遷移することができるようになっています。

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

GoRouteに一意の名前をつけることができます。設定するには宣言時にnameのパラメータを追加するだけです。

GoRoute(
   name: 'myPage',
   path: /* ... */,
   builder: /* ... */,
 ),

遷移する時はgoNamedを用います。

TextButton(
  onPressed: () {
    context.goNamed('myPage');
  },
  child: const Text('myPageへ遷移'),
),

こうすることで以下のメリットがあります。

  • パスの変更に柔軟になる
    • nameを用いて遷移するので、パスの変更があっても一括で変更できます。複数の画面でパスを指定して遷移していた場合は、それぞれの箇所でパスを変更する必要があります。

OSごとにテーマを設定する方法

準備の段階で、MaterialApp.routerCupertinoApp.routerを使用していましたが、PlatformApp.routerを用いるとMaterialやCupertinoデザインを区別することができます。

PlatformApp.routerを用いるにはflutter_platform_widgetsをインストールする必要があるのでご注意下さい。 https://pub.dev/packages/flutter_platform_widgets

AndroidはMaterial系のデザインに寄せてテーマを設定するなどということができます。

    return PlatformApp.router(
      routerConfig: router,
      material: (_, __) => MaterialAppRouterData(
        theme: ThemeData(
          primaryColor: Colors.red,
        ),
      ),
      cupertino: (_, __) => CupertinoAppRouterData(
        theme: const CupertinoThemeData(
          primaryColor: Colors.blue,
        ),
      ),
    );

最後に

go_routerを用いることで、URLベースのナビゲーションが可能とwebに似た操作ができるようになりました。またディープリンクに対応しやすくなるのも利点の一つかと思いました。

最後まで読んでいただきありがとうございました!