FirebaseAuthのログイン状態によって画面を切り替える
よく見るあの画面を作る
よく見かけるボトムナビゲーションバーで画面を切り替えると、ログインしていなければ、ログインページが表示されて、ログインしていたら画面が切り替わって、ログイン後のページが表示されるロジックを作るにはどうすればいいのか?
公式で解説されている authStateChanges を使います
現在の認証状態を確認する
Firebase Auth には、新規または既存の Flutter アプリケーションに安全な認証を統合するためのメソッドとユーティリティが用意されています。多くの場合、ユーザーの認証状態(ユーザーがログインしているのか、ログアウトしているのか)を把握する必要があります。
Firebase Auth では、Stream を使用して、この状態をリアルタイムで取得できます。Stream が呼び出されると、ユーザーの現在の認証状態を即時に提供します。また、認証状態が変更されるたびに、後続のイベントを提供します。
認証状態の変更をリッスンする方法は 3 つあります。
authStateChanges()
これらの変更を取得するには、FirebaseAuth インスタンスで authStateChanges() メソッドを呼び出します。
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});
ユーザーがログインしている状態によって、Widgetを切り替えるロジックはこのように作成します。
ログインの状態が、trueならログインしました! が表示されて、falseなら、ログインしていませんのページが表示されます。
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
if (snapshot.hasData) {
// ログインしている場合の表示するウィジェット
return Scaffold(
appBar: AppBar(
title: Text('ホーム'),
),
body: Center(
child: Text('ログインしました!'),
),
);
} else {
// ログインしていない場合の表示するウィジェット
return Scaffold(
appBar: AppBar(
title: Text('ホーム'),
),
body: Center(
child: Text('ログインしていません'),
),
);
}
},
);
}
}
デモアプリを作ってみた
実際にどんな動きをするのか確かめたくて、デモアプリを作成してみました。これは、もしかしたら、Flutter仕事で使ってる人も知らないかも???
今回作成したコード
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class PageD extends StatelessWidget {
const PageD({Key? key}) : super(key: key);
Widget build(BuildContext context) {
TextEditingController email = TextEditingController();
TextEditingController password = TextEditingController();
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
if (snapshot.hasData) {
return Scaffold(
body: Center(
child: Text(
'ログイン中...',
style: TextStyle(fontSize: 30),
),
),
);
} else {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 300,
child: TextField(
controller: email,
decoration: InputDecoration(
labelText: 'メールアドレスを入力してください',
filled: true,
fillColor: Colors.grey.shade200,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
)),
),
),
SizedBox(height: 20),
SizedBox(
width: 300,
child: TextField(
controller: password,
decoration: InputDecoration(
labelText: 'パスワードを入力してください',
filled: true,
fillColor: Colors.grey.shade200,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
)),
),
),
ElevatedButton(
onPressed: () async {
try {
await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: email.text, password: password.text);
} on FirebaseAuthException catch (e) {
if (e.code == 'invalid-email') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('メールアドレスのフォーマットが正しくありません'),
),
);
} else if (e.code == 'user-disabled') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('現在指定したメールアドレスは使用できません'),
),
);
print('現在指定したメールアドレスは使用できません');
} else if (e.code == 'user-not-found') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('指定したメールアドレスは登録されていません'),
),
);
} else if (e.code == 'wrong-password') {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('パスワードが間違っています'),
),
);
}
}
},
child: Text('新規登録'))
],
),
),
);
}
});
}
}
撮影した動画
全体のソースコード
使用したパッケージは、go_router, firebase_core, firebase_authだけです。
ソースコードは機能は少ないですが、ファイルが多いので記事には全部書いてないです。すいません🙇♂️
git clone して、pub getした後に、Firebase CLIを使用して、アプリとFirebaseを接続すれば、すぐに動作を試すことできるので、コピー&ペーストするよりもこっちの方が楽です。
もし、うまく行かなければ、Flutterのバージョンを合わせたり、新規作成したプロジェクトのlibディレクトリにサンプルコードを全てコピーして、コードを修正すれば使えるはずです。
まとめ
今回考えたロジックなんですけど、いつものように調べながら作ったわけではなくて、最近話題のChatGPTにコードを書いてもらって、ちょっと改造してデモアプリを作りました。
こんなもんがあったら、多分プログラミングスクール行かなくてもいい気がします😅
Discussion