【認証分岐】AuthGateでログイン済み・未ログインの画面を切り替える
このページでやること
このページでは、ログインしている人と、まだログインしていない人で、表示する画面を切り替えます。
今回作るのは、AuthGate という部品です。
AuthGate とは、ログイン状態を見て、表示する画面を振り分ける入口のようなWidgetです。
ログインしていない
↓
LoginPageを表示
ログインしている
↓
TeamListPageを表示
この仕組みを作ると、アプリを開いたときに、毎回ログイン画面を出す必要がなくなります。
今日のゴール
MaterialApp の home に、次のように書ける状態にします。
home: const AuthGate(),
そして、AuthGate の中でログイン状態を確認します。
class AuthGate extends StatelessWidget {
const AuthGate({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const LoadingPage(message: 'ログイン状態を確認しています...');
}
final user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return const TeamListPage();
},
);
}
}
まず出てくる単語
| 単語 | 一言説明 |
|---|---|
| 認証 | ユーザーが誰かを確認すること |
| ログイン状態 | 今、ユーザーがログインしているかどうか |
AuthGate | ログイン済みかどうかで画面を切り替える入口 |
StreamBuilder | 変化するデータを監視して画面を更新するWidget |
User | Firebase Authenticationのログインユーザー情報 |
snapshot | StreamBuilderが受け取った最新データ |
null | データがない状態 |
LoadingPage | 読み込み中に表示する画面 |
LoginPage | ログインしていない人に表示する画面 |
TeamListPage | ログイン済みの人に表示する画面 |
Widget とは、Flutterの画面部品のことです。
このページではnpmや環境変数は使いません
このページで使うのは、FlutterとFirebase Authenticationです。
npmは使いません。
npmとは、Node.jsのパッケージを管理する道具です。
環境変数も設定しません。
環境変数とは、パソコン全体で使う設定値のことです。
このページでやることはこれだけです。
main.dartを開く
↓
AuthGateを書く
↓
MaterialAppのhomeに設定する
↓
保存する
↓
flutter runで確認する
Step 1:main.dartを開く
Flutterプロジェクトの中で、次のファイルを開きます。
lib/main.dart
VS Codeを使っている場合は、ターミナルで次を実行してもOKです。
code lib/main.dart
code が使えない場合は、VS Codeの左側から lib/main.dart を開いてください。
Step 2:firebase_authのimportを確認する
main.dart の上の方に、次の1行があるか確認します。
import 'package:firebase_auth/firebase_auth.dart';
これは、Firebase AuthenticationをFlutterから使うための読み込みです。
import とは、別の機能をこのファイルで使えるようにすることです。
この1行がないと、FirebaseAuth や User が使えません。
Step 3:MaterialAppのhomeを確認する
WorkBoardApp の中にある MaterialApp を探します。
次のようになっているか確認してください。
return MaterialApp(
title: 'WorkBoard Firebase',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// テーマ設定
),
home: const AuthGate(),
);
大事なのは、この行です。
home: const AuthGate(),
home とは、アプリを起動したときに最初に表示する画面です。
つまり、このアプリでは、最初に AuthGate を表示します。
Step 4:AuthGateを追加する
AppColors の下あたりに、次のコードを追加します。
class AuthGate extends StatelessWidget {
const AuthGate({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const LoadingPage(message: 'ログイン状態を確認しています...');
}
final user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return const TeamListPage();
},
);
}
}
このコードで、ログイン状態を見て画面を切り替えます。
ログイン状態を確認中
↓
LoadingPage
ログインしていない
↓
LoginPage
ログインしている
↓
TeamListPage
Step 5:AuthGateの中身を短く理解する
まず、この部分です。
stream: FirebaseAuth.instance.authStateChanges(),
authStateChanges() は、ログイン状態の変化を監視する機能です。
監視とは、変化があったら気づけるように見ておくことです。
たとえば、
ログインした
ログアウトした
アプリを開いたらすでにログイン済みだった
という変化を見てくれます。
Step 6:StreamBuilderとは何か
この部分を見ます。
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
// 画面を返す
},
);
StreamBuilder は、変化するデータに合わせて画面を作り直すWidgetです。
今回は、ログイン状態が変わるたびに画面を切り替えます。
ログイン状態が変わる
↓
StreamBuilderが気づく
↓
画面を作り直す
User? の ? は、「Userかもしれないし、nullかもしれない」という意味です。
ログインしていれば User が入ります。
ログインしていなければ null になります。
Step 7:読み込み中の画面
この部分です。
if (snapshot.connectionState == ConnectionState.waiting) {
return const LoadingPage(message: 'ログイン状態を確認しています...');
}
ConnectionState.waiting は、まだログイン状態を確認中という意味です。
確認中に真っ白な画面になると不安なので、読み込み画面を出します。
ログイン状態を確認しています...
このような表示が出れば、ユーザーにとっても安心です。
Step 8:ログインしていない場合
この部分です。
final user = snapshot.data;
if (user == null) {
return const LoginPage();
}
snapshot.data には、ログイン中のユーザー情報が入ります。
ログインしていない場合は、null になります。
null とは、データがない状態のことです。
つまり、ここではこう判断しています。
userがない
↓
ログインしていない
↓
LoginPageを表示
Step 9:ログインしている場合
最後の部分です。
return const TeamListPage();
ここまで来たということは、user が null ではありません。
つまり、ログイン済みです。
だから、チーム一覧画面を表示します。
userがある
↓
ログイン済み
↓
TeamListPageを表示
Step 10:LoadingPageを用意する
AuthGate の中で LoadingPage を使っています。
まだ作っていない場合は、次のコードを追加します。
class LoadingPage extends StatelessWidget {
const LoadingPage({
super.key,
required this.message,
});
final String message;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.bg,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(
message,
style: const TextStyle(
color: AppColors.subText,
fontWeight: FontWeight.w600,
),
),
],
),
),
);
}
}
CircularProgressIndicator は、ぐるぐる回る読み込み表示です。
Scaffold は、Flutterの基本画面の土台です。
Step 11:まだLoginPageやTeamListPageがない場合
このページだけを先に試すと、次のエラーが出ることがあります。
The name 'LoginPage' isn't a class.
これは、LoginPage をまだ作っていないという意味です。
同じように、TeamListPage がまだない場合もエラーになります。
一時的に確認したい場合は、仮の画面を作ってください。
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('ログイン画面'),
),
);
}
}
class TeamListPage extends StatelessWidget {
const TeamListPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('チーム一覧画面'),
),
);
}
}
完成コードを使っている場合は、すでに LoginPage と TeamListPage があるので、この仮コードは不要です。
Step 12:保存する
main.dart を保存します。
Macの場合:
command + S
Windowsの場合:
Ctrl + S
Step 13:実行する
ターミナルで実行します。
flutter run
すでにアプリが起動している場合は、ターミナルで r を押します。
r
r はホットリロードです。
ホットリロードとは、アプリを起動したまま変更を反映する機能です。
Step 14:画面を確認する
まだログインしていない場合は、ログイン画面が表示されます。
WorkBoard
メールアドレス
パスワード
ログイン
すでにログインしている場合は、チーム一覧画面が表示されます。
トーク
まだチームがありません
ログアウトすると、またログイン画面に戻ります。
ログアウト
↓
AuthGateがログイン状態の変化に気づく
↓
LoginPageに切り替わる
画面の切り替わりイメージ
AuthGate は、アプリの入口に立っている受付のようなものです。
アプリ起動
↓
AuthGate
↓
ログイン済み?
↓
はい → TeamListPage
↓
いいえ → LoginPage
この仕組みがあると、画面遷移を自分で細かく書かなくても、ログイン状態に合わせて自然に画面が変わります。
1か所だけ変更してみる
読み込み中の文字を変えてみます。
この行を探します。
return const LoadingPage(message: 'ログイン状態を確認しています...');
次のように変えます。
return const LoadingPage(message: '少しだけお待ちください...');
保存して、ホットリロードします。
r
アプリ起動時の読み込み文字が変わればOKです。
確認したら、元に戻しておきます。
return const LoadingPage(message: 'ログイン状態を確認しています...');
よくあるエラーと直し方
| エラー | 原因 | 直し方 |
|---|---|---|
FirebaseAuth isn't defined | importがない | import 'package:firebase_auth/firebase_auth.dart'; を追加 |
User isn't a type | firebase_authのimportがない | firebase_auth.dart を確認 |
LoginPage isn't a class | LoginPageがまだない | LoginPageを作る |
TeamListPage isn't a class | TeamListPageがまだない | TeamListPageを作る |
| ずっと読み込み中 | Firebase初期化がうまくいっていない | Firebase.initializeApp() を確認 |
| ログイン後に切り替わらない | authStateChangesを使っていない | FirebaseAuth.instance.authStateChanges() を確認 |
FirebaseAuth isn't defined** が出たとき**
このエラーが出たら、main.dart の上に次の1行を追加します。
import 'package:firebase_auth/firebase_auth.dart';
保存します。
command + S
もう一度実行します。
flutter run
LoginPage** がないと言われたとき**
このページだけを先に進めている場合は、仮の LoginPage を作ってください。
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('ログイン画面'),
),
);
}
}
あとで本物のログイン画面に差し替えます。
TeamListPage** がないと言われたとき**
仮の TeamListPage を作ってください。
class TeamListPage extends StatelessWidget {
const TeamListPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('チーム一覧画面'),
),
);
}
}
あとで本物のトーク一覧画面に差し替えます。
最短作業まとめ
読むのが大変な人は、ここだけ見てください。
1. firebase_auth をimportする
import 'package:firebase_auth/firebase_auth.dart';
2. MaterialApp のhomeをAuthGateにする
home: const AuthGate(),
3. AuthGateを追加する
class AuthGate extends StatelessWidget {
const AuthGate({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const LoadingPage(message: 'ログイン状態を確認しています...');
}
final user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return const TeamListPage();
},
);
}
}
4. 保存する
command + S
5. 実行する
flutter run
チェックリスト
□ main.dartを開いた
□ firebase_authをimportした
□ MaterialAppのhomeをAuthGateにした
□ AuthGateを追加した
□ LoadingPageがある
□ LoginPageがある
□ TeamListPageがある
□ 保存した
□ flutter runで起動した
□ 未ログインならLoginPageが出る
□ ログイン済みならTeamListPageが出る
ミニ確認問題
Q1. AuthGateは何をするWidgetですか?
回答
ログイン済みか未ログインかを確認して、表示する画面を切り替えるWidgetです。
Q2. authStateChanges() は何を確認しますか?
回答
Firebase Authenticationのログイン状態の変化を確認します。
ログインしたとき、ログアウトしたとき、アプリ起動時のログイン状態を見ます。
Q3. user == null は何を意味しますか?
回答
ログインしているユーザーがいないという意味です。
そのため、ログイン画面を表示します。
Q4. このページでnpmや環境変数は必要ですか?
回答
必要ありません。
このページでは、main.dart に AuthGate を作り、ログイン状態で画面を切り替えるだけです。
このページのまとめ
AuthGateは、ログイン済み・未ログインを分ける入口。FirebaseAuth.instance.authStateChanges()でログイン状態を監視する。StreamBuilderは、変化するデータに合わせて画面を更新するWidget。user == nullなら未ログインなのでLoginPageを表示する。userがあるならログイン済みなのでTeamListPageを表示する。MaterialAppのhomeにAuthGateを設定する。- このページではnpmや環境変数は不要。
- 保存して実行し、画面が切り替わるか確認する。
次のページでやること
次のページでは、ログイン画面を作ります。
メールアドレスとパスワードを入力して、Firebase AuthenticationにログインするUIを作っていきます。
