【Flutter備忘録】Firebaseを使って再起動後もログイン状態を保持する


# はじめに

**Flutter**を利用したアプリ開発をやっている中で
個人的に詰まった部分を定期的に記事にしていこうと思います。

# 今回実装すること
**Firebase**の**FirebaseAuth**を利用して, <br>再起動してもログイン状態を保持する機能の実装

#実装
今回は`Provider`を利用してログイン状態をアプリを立ち上げた後にどこでも使用できるように`UserState`に保持しておく
→`initState`でProviderを使う時は宣言時に`listen:false`を追加し、状態を監視できないようにする(初期状態で監視する必要がないため?エラーを吐くのかもしれない)

**Firebase**ではユーザの認証状態を自動的に保持し,再起動時に復元してくれているので、`FirebaseAuth.instance.currentUser`で現在ログインされているユーザの状態を取得し、<br>その状態によって後は遷移を書くことで実装することができた。


```dart:ログインチェック部分
    final currentUser = await FirebaseAuth.instance.currentUser();
    final userState = Provider.of<UserState>(context,listen: false);
    if(currentUser == null){
      Navigator.pushReplacementNamed(context,"/login");
    }else{
      userState.setUser(currentUser);
      Navigator.pushReplacementNamed(context, "/home");
    }
```

```dart:main.dart
import 'dart:math';
import 'package:card_manager/page_manager.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:provider/provider.dart';
import 'login_page.dart';

void main() {
  runApp(MyApp());
}

class UserState extends ChangeNotifier{
  FirebaseUser user;
  void setUser(FirebaseUser currentUser){
    user = currentUser;
    notifyListeners();
  }
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  final UserState user = UserState();

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserState>.value(
        value: user,
        child: MaterialApp(
          //デバックラベル非表示
          debugShowCheckedModeBanner: false,
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: LoginCheck(),
          initialRoute: "/",
          routes:<String, WidgetBuilder>{
            AddRecord.routeName: (BuildContext context) => AddRecord(),
            "/login":(BuildContext context) => LoginPage(),
            "/home":(BuildContext context) => PageManager(),


          },
        )
    );
  }
}

class LoginCheck extends StatefulWidget{
  LoginCheck({Key key}) : super(key: key);

  @override
  _LoginCheckState createState() => _LoginCheckState();

}

class _LoginCheckState extends State<LoginCheck>{
  //ログイン状態のチェック(非同期で行う)
  void checkUser() async{
    final currentUser = await FirebaseAuth.instance.currentUser();
    final userState = Provider.of<UserState>(context,listen: false);
    if(currentUser == null){
      Navigator.pushReplacementNamed(context,"/login");
    }else{
      userState.setUser(currentUser);
      Navigator.pushReplacementNamed(context, "/home");
    }
  }

  @override
  void initState(){
    super.initState();
    checkUser();
  }
  //ログイン状態のチェック時はこの画面が表示される
　//チェック終了後にホーム or ログインページに遷移する
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Container(
          child: Text("Loading..."),
        ),
      ),
    );
  }
}
```



# 最後に
- ログイン状態が自動的に保持されるFirebaseは便利だと思った反面、正しく理解していないと不具合が起きた際に対処できないと思った。
- 結局、自分も実装してみて`currentUser`で再起動後も保持されていることを知ったので、公式の解説がどこにあるかはわかっていない(知っている方がいたらコメントで教えてくださると助かります！)

# 今までの備忘録
- [DataTableに関して](https://qiita.com/TheGiovanni/items/29599e0f5e52e7f493f8)


# 参考文献
- [Firebase：ユーザーがログインしているかどうかを確認する方法は？](https://www.it-swarm.dev/ja/android/firebase%EF%BC%9A%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%8C%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F/831848082/)
- [Firebaseでユーザを管理する](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)