こんにちは、株式会社Pentagonの小寺です。
これまで画面遷移や遷移時にデータを渡すためにGetXを使用していましたが、GetXを廃止してgo_routerを採用することにしたため、go_routerの使用方法や良さについてまとめていきたいと思います。
【こんな人に読んで欲しい】
go_routerを使用しようと考えている方
画面遷移時にデータを渡したい方
【この記事を読むメリット】
go_routerの使用方法がわかる
画面遷移時にデータの渡し方がわかる
そもそもなぜGetXを廃止したのか
これまで使用していたGetXは遷移以外の機能も含まれており、不具合があった際に調査が困難であったため廃止しました。
なぜ新たにgo_routerを使用したかというと、遷移が簡単であり、公式(flutter.dev)によりメンテナンスされているためです。
使用するパッケージ
今回は画面遷移、遷移時に値を返すためにgo_routerを使用しました。
https://pub.dev/packages/go_router
ルーティングの設定
final GoRouter router = GoRouter(
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: ‘/sign_up’,
builder: (context, state) => const SettingScreen(),
),
],
);
routerの設定は上記のようにGoRouter()のroutes内にGoRoute()を設定しpathとbuilderを設定します。設定したrouterはMaterialApp.router内にセットします。
MaterialApp.router(
routerConfig: router,
);
go_routerの遷移方法
遷移パターン | go_routerの場合 | Flutter標準の場合 |
---|---|---|
渡す値がない場合かつ前の画面に戻る | GoRouter.of(context).push(location名); GoRouter.of(context).pushNamed(path名); | Navigator.of(context).push(); Navigator.of(context).pushNamed(); |
渡す値がない場合 かつ 前の画面に戻ることができない 新しい画面に遷移し、元の画面をスタックから削除する | GoRouter.of(context).go(location名); | GoRouter.of(context).goNamed(path名); |
渡す値がない場合 かつ 前の画面に戻ることができない 新しい画面をルートにする | GoRouter.of(context).pushReplacement(location名); GoRouter.of(context).pushReplacementNamed(path名); | Navigator.of(context).pushReplacement(); Navigator.of(context).pushReplacementNamed(); |
渡す値がある場合 ※遷移方法については渡す値がない場合と同じため代表してpushのみ記載しております | GoRouter.of(context).push(path名, extra: args); | Navigator.of(context).pushNamed(path名, extra: args); |
前のページに戻る | GoRouter.of(context).pop(); | Navigator.of(context).pop(); |
値を渡す方法
今回値を渡す方法については、sign_up_screenを使用して説明していこうと思います。
コードについてはgo_routerで値を渡す、受け取る箇所に絞ってコードを記載した上で流れを説明します。
sign_up_screen_arguments
class SignUpScreenArguments {
const SignUpScreenArguments({
this.signUpScreenMode = SignUpScreenMode.init,
required this.email,
});
final SignUpScreenMode signUpScreenMode;
final String email;
}
enum SignUpScreenMode {
init,
sendMail,
}
go_routerの設定
// サインアップ画面
GoRoute(
path: ‘/signUp’,
builder: (context, state) =>
SignUpScreen(state.extra as SignUpScreenArguments),
),
sign_up_screen
class SignUpScreen extends HookConsumerWidget {
const SignUpScreen(this.args, {Key? key}) : super(key: key);
final SignUpScreenArguments args;
/// 初期表示レイアウト
Widget getInit(BuildContext context, WidgetRef ref) {
final notifier = ref.read(signUpScreenModelProvider.notifier);
final emailController = notifier.emailController;
final isSecure =
ref.watch(signUpScreenModelProvider.select((value) => value.isSecure));
final passwordController = notifier.passwordController;
final passwordTextVerificationFailure = ref.watch(
signUpScreenModelProvider
.select((value) => value.passwordTextVerificationFailure),
);
return SizedBox(
width: double.infinity,
child: AcceptButton(
label: '登録',
textStyles: const [
fontSize14,
weight700,
white,
],
onPressed: () async {
if (formKey.currentState?.validate() ?? false) {
OriginalProgress.show(context);
await notifier.signUp().then(
(value) {
OriginalProgress.dismiss(context);
GoRouter.of(context)
..pop()
..push(
AppRouter.signUp,
extra: SignUpScreenArguments(
signUpScreenMode: SignUpScreenMode.sendMail,
email: emailController.text,
),
);
},
onError: (dynamic e) {
OriginalProgress.dismiss(context);
OriginalProgress.showError(
context,
e.toString(),
);
},
);
}
},
),
),
);
}
/// メール送信レイアウト
Widget getSendMailLayout(
SignUpScreenArguments args,
) {
return Text(
args.email,
style: textStyle(
const [
fontSize14,
weight400,
],
),
);
}
}
sign_up_screenは前提としてSignUpScreenModeにあるinit(新規登録画面)とsendMail(メール送信画面)の2つのモードがあります。
GoRouterでの値の受け渡しはnull許容で渡すことができますがsign_up_screenには必ず値を渡したいのでnull許容せずに値を渡しています。
extraで渡された値はsign_up_screenで
final SignUpScreenArguments args;
として受け取られています。
sign_up_screen内にある登録ボタンを押下すると、下記の値を渡した遷移が行われます。
挙動としては登録時に入力したemailを受け渡してメール送信画面へとSignUpScreenModeを変更しています。
GoRouter.of(context)
..pop()
..push(
AppRouter.signUp,
extra: SignUpScreenArguments(
signUpScreenMode: SignUpScreenMode.sendMail,
email: emailController.text,
),
);
実際の動き
まとめ
冒頭でも述べたように、go_routerはGetXとは違い遷移以外の機能がないため不具合があった際に調査がGetXに比べ容易である点、公式(flutter.dev)により定期的にメンテナンスされている点からgo_routerへの変更をしました。
値を渡す段階でエラーハンドリングすることができ、値を渡す際に予期しないエラーを未然に防ぐことができる点が使用していて便利と思った点です。
おまけ
Flutterに関する知識を深めたい方には、『Flutterの特徴・メリット・デメリットを徹底解説』という記事がおすすめです。
この記事では、Flutter アプリ開発の基本から、Flutter とは何か、そして実際のFlutter アプリ 事例を通じて、その将来性やメリット、デメリットまで詳しく解説しています。
Flutterを使ったアプリ開発に興味がある方、またはその潜在的な可能性を理解したい方にとって、必見の内容となっています。
ぜひ一度ご覧ください。