Chapter 23

[v0.14.0以下版] Userを状態として持つFirebase Auth のControllerを作成する

村松龍之介
村松龍之介
2023.02.12に更新

FirebaseのAuthenticationを使うと、比較的簡単に認証周りを実装できてありがたいですよね。

  • Userの状態が変化したとき(ログイン・ログアウト等)で通知を受けて再構築させる
  • 認証周りのロジックを受け持つコントローラを作る

を目的にStateNotifierを使って実装していきます。

サンプルリポジトリのリンク

auth_controller StateNotifierProviderの実装
https://github.com/Riscait/flutter_fire_playground/blob/main/lib/src/features/authenticator/auth_controller.dart

auth_page デモページ
https://github.com/Riscait/flutter_fire_playground/blob/main/lib/src/pages/auth_page.dart

StateNotifierクラスの定義

Userを状態に持つ、AuthControllerクラスを作成します。

コンストラクタの引数で、 initialUser として、最初の User を受け取れるようにします。
コンストラクタのBodyで、 userChanges() を使って User の変更を購読、Stateを最新に保つようにしています。

auth_controller.dart
class AuthController extends StateNotifier<User?> {
  // ----- Constructor ----- //
  AuthController({User? initialUser}) : super(initialUser) {
    // Userの変更を検知して状態を更新
    _auth.userChanges().listen((user) {
      state = user;
    });
  }

  final _auth = FirebaseAuth.instance;

  /// FirebaseAuthの匿名認証でサインインする
  Future<void> signInWithAnonymous() async {
    final userCredential = await _auth.signInAnonymously();
    state = userCredential.user;
  }

  /// アカウントを削除する
  Future<void> deleteAccount() async {
    await state?.delete();
  }

  /// Firebase Auth User の表示名を更新する
  Future<void> updateDisplayName(String newName) async {
    await state?.updateProfile(displayName: newName);
  }
}

一例としていくつかのメソッドを追加しました。

  • 匿名サインイン
  • アカウント削除
  • ユーザーの表示名更新

必要に応じて、Sign in with Apple, Google 等のメソッドを追加できます。

Providerの定義

AuthControllerを提供するProviderを作成します。

auth_controller.dart
final authControllerProvider = StateNotifierProvider<AuthController, User?>(
  (ref) => AuthController(initialUser: FirebaseAuth.instance.currentUser),
);

Widgetから使用する

任意のWidgetで、Userの displayName を表示し、サインインとアカウント削除ボタンを表示させる場合は以下のように書きます。

some_page.dart

Widget build(BuildContext context, ScopedReader watch) {
  // `User?` (nullなら未サインイン)
  final user = watch(authControllerProvider);
  // `AuthControlle`
  final authController = watch(authControllerProvider.notifier);

  return Scaffold(
    // `displayName` は匿名認証・パスワード認証以外でサインインしたときに利用できる
    appBar: AppBar(title: const Text('${user?.displayName ?? '名無し'}さん'))
    body: user == null
      ? ElevatedButton(
          onPressed: authController.signInWithAnonymous,
          child: const Text('サインイン'),
        )
      : OutlinedButton(
          onPressed: authController.deleteAccount,
          child: const Text('アカウント削除'),
        ),
  );
}

このように authControllerProvider を Widget や他のProvider内で読み取ることで…

  • 最新の User 状態を取得
  • Firebase Auth や User に関するロジックを呼び出せる

ようになりました🎉

参考リンク

Flutter アプリに Firebase を追加する
https://firebase.google.com/docs/flutter/setup?hl=ja

Authentication | FlutterFire
https://firebase.flutter.dev/docs/auth/overview/