7
2

More than 1 year has passed since last update.

【Flutter】go_routerで「○秒後にリダイレクト」を表現してみた。

Posted at

go_routerのGoRouterクラスにはredirectという関数があります。こちらの関数はナビゲーションイベントが発生する毎に発火し、条件にあった画面にリダイレクトさせることができます。

class GoRouterSample extends StatelessWidget {
  ...
  late final _router = GoRouter(
    redirect: (state) {
    // ここにリダイレクト先と条件を書いていく
    },
  );
}

今回はこのredirectを利用してwebページによくあるような「○秒後にリダイレクト」を表現してみました。

実装内容

秒数を管理するクラスを定義(ValueNotifier便利だな〜)

count.dart
class Count extends ValueNotifier<int> {
  Count(super.value);

  void countDown() {
    value = value - 1;
  }

  void resetCount() {
    value = 5;
  }
}

main.dartにgo_routerの諸々を定義。アプリ起動時にget_itというパッケージでCountクラスをシングルトンとして登録しています。

main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // get_itを使用してCountクラスをシングルトンとして登録      
  GetIt.I.registerSingleton(Count(5));

  runApp(
    GoRouterSample(),
  );
}

class GoRouterSample extends StatelessWidget {
  GoRouterSample({Key? key}) : super(key: key);
  // get_itに登録したCountクラスを取得                                                                     
  final countRepository = GetIt.I<Count>();

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationProvider: _router.routeInformationProvider,
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
      );

  late final _router = GoRouter(
    initialLocation: '/login',
    // ルート診断情報の出力を有効にする(なくても良い)
    debugLogDiagnostics: true,
    // Listenableクラスに変化があればルートがリフレッシュされる(redirectが発火する)
    refreshListenable: countRepository,
    routes: [
      GoRoute(
        path: '/login',
        builder: (context, state) => TopPage(),
      ),
      GoRoute(
        path: '/first',
        builder: (context, state) => FirstLoginPage(),
      ),
      GoRoute(
        path: '/home',
        builder: (context, state) => HomePage(),
      ),
    ],
    // ナビゲーションイベントが起こるたびに発火
    redirect: (state) {
      // countが0になったらcountをリセットし、ホーム画面にリダイレクト
      // (countを0にしないと無限ループしてしまうため)
      if (countRepository.value == 0) {
        countRepository.resetCount();
        return '/home';
      }
      // nullを返すと本来の遷移先に遷移してくれる
      return null;
    },
  );
}

GoRouterコンストラクタのrefreshListenableプロパティに監視したいクラスを指定します(ChangeNotifierやValueNotifer等)。指定したクラス(正しくは状態変数?)に変更があった場合はルートをリフレッシュしてくれます(つまりredirectを発火してくれる)

今回はこれを活用しValueNotifier継承クラスでint型の秒数を管理。1秒ごとに-1して状態変数を更新。ValueNotifier継承クラスが更新されたためredirectが発火され、もし秒数が0の場合はホーム画面にリダイレクト。といった形で実装しています。

FirstLoginPageではTimerを使用して1秒ごとに状態変数を-1するように実装しています。

first_login.dart
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_playground/presentasion/pages/playground/go_router/main.dart';
import 'package:get_it/get_it.dart';

class FirstLoginPage extends StatefulWidget {
  const FirstLoginPage({Key? key}) : super(key: key);

  @override
  State<FirstLoginPage> createState() => _FirstLoginPageState();
}

class _FirstLoginPageState extends State<FirstLoginPage> {
  // 登録済みのCountクラスを取得
  final count = GetIt.I<Count>();
  late Timer _timer;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(
      const Duration(seconds: 1),
      (Timer timer) {
        // 1秒ごとにcount.valueを-1している
        count.countDown();
        setState(() {});
      },
    );
  }

  @override
  void dispose() {
    super.dispose();
    _timer.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('初回ログイン'),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SizedBox(
                  child: Text(
                    count.value.toString(),
                  ),
                ),
                const Text('秒後にホーム画面に遷移します。'),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

(TopPageとHomePageは特段解説する必要はないと思うので省きます。)

今回は解説というよりは「こんなもの作ってみました〜」という感じなので具体的な説明は省きましたが、go_routerでリダイレクトができるってことは伝わったかなと思います。どなたかの参考になれば嬉しいです。

参考

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2