web-dev-qa-db-ja.com

FlutterでFirebase Authenticationの状態を管理する方法は?

サインアップとログインが含まれるWelcomeScreenと、ユーザーがログインした後にリダイレクトするHomeScreenがあります。認証データを管理するために、auth.Dartstaticプロパティおよびメソッドを使用して、同じデータを持つすべてのページでそれらにアクセスできるようにします。

import 'package:firebase_auth/firebase_auth.Dart';

class Auth {

  static final auth = FirebaseAuth.instance;

  static Future<void> logout() async {
    await auth.signOut();
  }

  static Future<void> loginUser(String userEmail, String userPassword) async {
    await auth.signInWithEmailAndPassword(email: userEmail, password: userPassword);
  }

  static Future<FirebaseUser> getCurrentUser() async {
    return await auth.currentUser();
  }
}

main.Dartファイル、私はStreamBuilderを使用して、認証データの変更に基づいて現在の画面を変更しています。私はこのStreamBuilderコードを この回答 から取得しました。

home: StreamBuilder<FirebaseUser>(
  stream: Auth.auth.onAuthStateChanged,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return HomeScreen();
    } else {
      return WelcomeScreen();
    }
  },
),

ログイン画面で、以下のコードを使用してログインをトリガーしています。

Future<void> login() async {
    ...

    try {
      await Auth.loginUser(userEmail, userPassword);
      var user =  await Auth.getCurrentUser();
      print(user.displayName); // This works
    } catch (error) {
      print(error.message);
    }
  }

私が使用している静的メソッドがFirebase authを処理する正しい方法であるかどうかはわかりませんが、機能しているようです。ログイン後、ログインしているユーザーの名前を表示できますが、StreamBuildermain.Dartは、更新された認証データを反映していません。つまり、ページを変更していません。

静的メソッドのためか、StreamBuilderの実装に問題があるためでしょうか?

8
gegobyte

私の意見では、フラッターでFirebase認証を管理する最良の方法は、プロバイダーパッケージを使用することです。 Authクラスには、onAuthStateChnagedメソッドという重要なものが1つありません。 Authクラス内でonAuthStateChangedのゲッターとしてストリームを作成できます。 AuthクラスはChangeNotifierクラスを拡張します。 ChangeNotifierクラスは、flutter APIの一部です。

class Auth extends ChangeNotifier {

    final FirebaseAuth _auth = FirebaseAuth.instance;

    // create a getter stream
    Stream<FirebaseUser> get onAuthStateChanged => _auth.onAuthStateChanged;

    //Sign in async functions here ..

}

MaterialAppをChangeNotifierProvider(プロバイダーパッケージの一部)でラップし、次のようにcreateメソッドでAuthクラスのインスタンスを返します。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Auth(),
      child: new MaterialApp(
      home: Landing(),
      ),
    );
  }
}

次に、ランディングページをステートレスウィジェットとして作成します。 ConsumerまたはProvider.of(context)とストリームビルダーを使用して、認証の変更をリッスンし、必要に応じてログインページまたはホームページをレンダリングします。

class Landing extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Auth auth = Provider.of<Auth>(context);
    return StreamBuilder<FirebaseUser>(
      stream: auth.onAuthStateChanged,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          FirebaseUser user = snapshot.data;
          if (user == null) {
            return LogIn();
          }
          return Home();
        } else {
          return Scaffold(
            body: Center(
              child: CircularProgressIndicator(),
            ),
          );
        }
      },
    );
  }
}

プロバイダーによる状態管理の詳細については、正式なフラッタードキュメントをご覧ください。このリンクに従ってください: https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

0
humanshado