はじめに
最近した業務でFirebaseAuthのEmail認証が完了したタイミングで画面遷移をする必要があり方法がわからなくて困ったため私と同じように困っている方のために残しておきたいと思います。
結論
- FirebaseAuthの
currentUser
に用意されているreload
関数を毎秒実行することで解決しました。
2021/11/7時点の情報のため、FlutterやFirebase関連のバージョンにより実装方法が大きく変更されることがございます。
なぜFirebaseAuthのauthStateChangesを使わなかったのか
authStateChangesを使わない理由
@tsuzuki817 さんから質問頂いたので追記
- トリガーが発火する条件が以下にあり、メール認証をしたかどうかをリアルタイムに検知できないため
Events are fired when the following occurs:
・ Right after the listener has been registered.
・ When a user is signed in.
・ When the current user is signed out.
The stream is not expected to fire when the user is verified. You can read what each of the streams do from the documentation here:
https://firebase.flutter.dev/docs/auth/usage#authentication-state
執筆時の環境
- Flutter2.5.2
-
flutter_riverpod
を使用
前提
- Flutter web
- Firebaseの設定が完了していること。
- FirebaseAuthの
sendEmailVerification
メソッドが実行されていてメール認証が未完了であること。
実装方法
View
class SamplePage extends ConsumerWidget {
const SamplePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ScopedReader watch) {
final model = watch(sendEmailModelProvider);
// emailVerifiedがtrueへ変わったらSampleSecondPageへ遷移
if (model.emailVerified == true) {
return const SampleSecondPage();
}
return const Scaffold(
body: Center(
child: Text('最初の画面'),
),
);
}
}
ViewModel
毎秒実行している処理をtimer.cancel()
で止めないと遷移後も遷移前の最初の画面で実行し続けてしまうため、今回はemailVerified
がtrue
になったらcancelしています。
final sampleModelProvider =
ChangeNotifierProvider((_) => SampleModel()..timerReading());
class SampleModel extends ChangeNotifier {
bool emailVerified = false;
// 毎秒reload関数を実行してAuthのemailVerifiedの状態を監視している
void timerReading() {
Timer.periodic(const Duration(seconds: 1), (Timer timer) async {
await FirebaseAuth.instance.currentUser!.reload();
emailVerified = FirebaseAuth.instance.currentUser!.emailVerified;
// emailVerifiedがtrueに変更されたタイミングで毎秒処理を止めています。
if (emailVerified == true) {
timer.cancel();
}
notifyListeners();
});
}
}