はじめに
FlutterのルーティングライブラリであるFluroの使い方について、簡単なTODOアプリの実装を通して説明していきます。
環境
本記事のサンプルアプリで使用しているライブラリのバージョンです。
- flutter: 2.8.1
- fluro: 2.0.3
インストール
$ flutter pub add fluro
Fluroの使い方
まずはFluroを使ったルーティングの設定方法から説明していきます。
ルーティングの初期設定
Flutterのエントリーポイントであるmain()
メソッド内で、ルーティングの初期設定を行なっています。
lib/main.dart
import 'package:fluro/fluro.dart'; import 'package:flutter/material.dart'; import 'router/routes.dart'; void main() { // FluroRouterオブジェクトの初期化 final router = FluroRouter(); // ルーディングの設定 Routes.configureRoutes(router); // 他のWidgetからも呼び出せるようにFluroRouterオブジェクトをrouterプロパティに設定 TodoApp.router = router; runApp(const TodoApp()); } class TodoApp extends StatelessWidget { static FluroRouter? router; const TodoApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // 最初のrouteを「/」に設定 // Fluroから提供されているgeneratorをonGenerateRouteに設定 return MaterialApp( initialRoute: '/', onGenerateRoute: TodoApp.router?.generator); } }
main()
メソッド内では、Fluroを使ってルーティングをするために必要なFluroRouter()
オブジェクトの定義と、routeと画面の紐付けをするために作成したメソッドであるRoutes.configureRoutes
を呼び出しています。
また、WidgetツリーのルートであるTodoApp
のstaticプロパティrouter
に、FluroRouter
オブジェクトを設定することで、他画面でもFluroルーターにアクセスできるようにします。
// FluroRouterオブジェクトの初期化 final router = FluroRouter(); // ルーディングの設定 Routes.configureRoutes(router); // 他のWidgetからも呼び出せるようにFluroRouterオブジェクトをrouterプロパティに設定 TodoApp.router = router;
以下では、MaterialApp
のコンストラクタでinitialRoute: '/'と定義することで最初に遷移するrouteを「/」に設定しています。
また、onGenerateRoute: TodoApp.router?.generator
と定義することでルーティング設定をFlutter側に渡しています。
// 最初のrouteを「/」に設定 // Fluroから提供されているgeneratorをonGenerateRouteに設定 return MaterialApp( initialRoute: '/', onGenerateRoute: TodoApp.router?.generator); }
routeと遷移先画面の紐付け
main()
メソッドから呼んでいるRoutes.configureRoutes
メソッドでrouteと遷移先画面の紐付けをしていきます。
lib/router/routes.dart
import 'package:fluro/fluro.dart'; import 'package:flutter/material.dart'; import 'package:flutter_basic_todo/model/todo.dart'; import 'package:flutter_basic_todo/pages/account_page.dart'; import 'package:flutter_basic_todo/pages/add_todo_page.dart'; import 'package:flutter_basic_todo/pages/todo_detail_page.dart'; import 'package:flutter_basic_todo/pages/todo_list_page.dart'; // 遷移先に渡したい値がない時に使用するハンドラー // 単に引数で設定した遷移先の画面を返すだけのハンドラーになっている Handler createBasicHandler(Widget targetWidget) { return Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { return targetWidget; }); } // アカウント画面に遷移する時に呼び出されるハンドラー // パスに設定したuserNameパラメーターを遷移先の画面に渡している Handler accountPageHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { return AccountPage(params['userName']!.first); }); // TODO詳細画面に遷移する時に呼び出されるハンドラー // Todoオブジェクトを遷移先の画面に渡している Handler todoDetailPageHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { final args = context?.settings?.arguments as Todo; return TodoDetailPage(args); }); class Routes { // routeと遷移先の画面、遷移時に呼び出されるハンドラーを設定している static void configureRoutes(FluroRouter router) { router // 最初に遷移する画面、route: '/'でTODOリスト画面に遷移する ..define('/', handler: createBasicHandler(const TodoListPage())) // route: '/add'でTODO追加画面に遷移するように設定している ..define('/add', handler: createBasicHandler(const AddTodoPage())) // route: '/account/:userName'でアカウント画面に遷移する // ':userName'パラメーターでユーザー名を遷移先の画面に渡している ..define('/account/:userName', handler: accountPageHandler) // route: '/detail'でTODO詳細画面に遷移する // Todoオブジェクトを遷移先の画面に渡している ..define('/detail', handler: todoDetailPageHandler); } }
Fluroではルーティングの設定を、routeとハンドラー関数をマッピングする形式で実施します。
例えば、..define('/detail', handler: todoDetailPageHandler)
では、画面遷移時に/detail
がrouteとして指定された時には、ハンドラー関数としてtodoDetailPageHandler
を呼び出す、という感じです。
上記のRoutes.configureRoutes
メソッドで実施しているルーディングの設定とそのルーティングを使った画面遷移の方法について詳しく説明していきます。
値を渡さない場合の画面遷移
まず、以下のルーディング設定では、route/add
に合致した場合にハンドラーcreateBasicHandler(const AddTodoPage())
を呼ぶ、という設定をしています。
createBasicHandler()
では、引数として渡されたWidgetをそのまま返すという処理を行なっているため、route/add
に合致するとTODO追加画面(AddTodoPage
)に遷移します。
// 遷移先に渡したい値がない時に使用するハンドラー // 単に引数で設定した遷移先の画面を返すだけのハンドラーになっている Handler createBasicHandler(Widget targetWidget) { return Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { return targetWidget; }); } class Routes { static void configureRoutes(FluroRouter router) { router // route: '/add'でTodo追加画面に遷移するように設定している ..define('/add', handler: createBasicHandler(const AddTodoPage())) }
上記のルーティング設定を使用して画面遷移を実施する場合は以下のようになります。
// TODO追加画面に遷移する TodoApp.router?.navigateTo(context, '/add', transition: TransitionType.material);
上記のFluroのFluroRouter.navigateTo
メソッドはFlutterのNavigator.pushを拡張したものなので基本的な使い方はNavigator.push
と同じになります。
例えば、TODO追加画面から遷移元の画面に戻した値を受け取るときは、FlutterのNavigatorを使用した場合と同様に以下の書き方になります。
// TODO追加画面 // 遷移元の画面に値('send value')を渡す TodoApp.router?.pop(context, 'send value');
// 遷移元の画面 // 遷移先から戻る時に渡された値('send value')を受けとる final newListText = await TodoApp.router?.navigateTo(context, '/add', transition: TransitionType.material);
なお、遷移元の画面に戻る時に使用するFluroRouter.pop()
は、裏側でFlutterのNavigator.pop()を呼んでいるだけなので、両者に違いはありません。
パラメーター付きrouteで遷移先画面に値を渡す
// アカウント画面に遷移する時に呼び出されるハンドラー // パスに設定したuserNameパラメーターを遷移先の画面に渡している Handler accountPageHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { return AccountPage(params['userName']!.first); }); class Routes { static void configureRoutes(FluroRouter router) { router // route: '/account/:userName'でアカウント画面に遷移する // ':userName'パラメーターでユーザー名を遷移先の画面に渡している ..define('/account/:userName', handler: accountPageHandler) } } }
上記のルーティング設定は、route/account/[渡したい値]
に合致した場合にハンドラーaccountPageHandler
を呼び出して、アカウント画面(AccountPage
)にrouteに含めたパラメーターを渡して遷移する、という設定になります。
上記のルーティング設定を使用して画面遷移を実施する場合は以下のようになります。
const accountName = '花籠総矢'; // アカウント画面に遷移する TodoApp.router?.navigateTo(context, '/account/$accountName');
上記のように画面遷移することで、遷移先の画面に値'花籠総矢'
を渡すことができます。
オブジェクトを遷移先の画面に渡す
パラメーター付きrouteを使う方法以外にも、BuildContext.settings.arguments
経由で値を渡す方法もあります。
以下のルーティング設定では、route/detail
に合致した場合にTodo
オブジェクトをTODO詳細画面(TodoDetailPage
)に渡す設定をしています。
// Todo詳細画面に遷移する時に呼び出されるハンドラー // Todoオブジェクトを遷移先の画面に渡している Handler todoDetailPageHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { final args = context?.settings?.arguments as Todo; return TodoDetailPage(args); }); class Routes { static void configureRoutes(FluroRouter router) { router // route: '/detail'でTodo詳細画面に遷移する // Todoオブジェクトを遷移先の画面に渡している ..define('/detail', handler: todoDetailPageHandler); }
上記のルーティング設定を使用して画面遷移を実施する場合は以下のようになります。
TodoApp.router?.navigateTo( context, '/detail', routeSettings: RouteSettings( arguments: Todo('todo-101', 'ゴミ出し'), ), );
上記の画面遷移では、遷移先の画面(TodoDetailPage
)にTodo('todo-101', 'ゴミ出し')
を渡しています。