🤩

[Flutter]SharedPreferencesを用いたログイン保持の方法(備忘録)

2023/11/06に公開1

はじめに

アプリを作成している時にログイン機能を作成しました!
しかし、毎回ログインするためのデータを入力するのは面倒で困ってました...
そこでアプリに必要不可欠と言っても過言ではないログイン保持機能を実装を備忘録として残しておきます。

参考にしたもの

今回はJBoyさんの「Flutterでログイン後の状態を維持する」の記事を参考にさせていただきました。
https://zenn.dev/flutteruniv_dev/articles/902b184146ea94

開発環境

Flutterバージョン

Flutter 3.13.7 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 2f708eb839 (4 weeks ago)2023-10-09 09:58:08 -0500
Engine • revision a794cf2681
ToolsDart 3.1.3DevTools 2.25.0

パッケージバージョン

shared_preferences: ^2.0.15

実装コード

最初に今回利用するコードを記載しておきます。

今回は、FirebaseAuthを利用した匿名ログインユーザーのログイン保持機能を実装します。

(本記事はログイン保持のロジックのみ)

PreferencesManager

SharedPreferencesの機能を利用している部分をPreferencesManagerにまとめて利用していきます。

class PreferencesManager {
  factory PreferencesManager() {
    return _incessance;
  }
  PreferencesManager._internal();
  static late final SharedPreferences _preferences;
  static final PreferencesManager _incessance = PreferencesManager._internal();
  Future<void> set(SharedPreferences preferences) async =>
      _preferences = preferences;
  Future<bool> get isLogin async {
    return _preferences.getBool(_isLogin) ?? false;
  }
  Future<void> setIsLogin({
    required bool isLogin,
  }) async {
    await _preferences.setBool(_isLogin, isLogin);
  }
}

setIsLoginを使用する場面

ログインした際にチェックしたいのでonPressedの中にそのまま記載します。

ElevatedButton(
  child: const Text('サインインせずに利用'),
  onPressed: () async {
    await PreferencesManager().setIsLogin(isLogin: true);
    context.go(Routes.main);
  },
);

get isLoginを使用する場面

isLoginの値をProviderで管理しています。


class SplashPageState with _$SplashPageState {
  const factory SplashPageState({
    bool? isLogin,
  }) = _SplashPageState;
}

final splashPageProvider =
    StateNotifierProvider.autoDispose<SplashPageController, SplashPageState>(
        (ref) {
  return SplashPageController();
});

class SplashPageController extends StateNotifier<SplashPageState> {
  SplashPageController() : super(const SplashPageState()) {
    init();
  }

  Future<void> init() async {
    if (_isAuthenticated && mounted) {
      final isLogin = await PreferencesManager().isLogin;
      state = state.copyWith(isLogin: isLogin);
    }
  }
}

SplashPage.dartの中身

isLoginの値によって画面遷移先を設定します。

Consumer(
      builder: (context) {
        ref.listen<bool?>(splashPageProvider.select((s) => s.isLogin),
            (_, isLogin) async {
          if (isLogin == false) {
            context.go(Routes.signin);
          }else{
	    context.go(Routes.main);
          }
        });
        return Scaffold(
          body: Center(
            child: Container(
              child: const Text('Loading...'),
            ),
          ),
        );
      },
    );

注意事項

下記の部分を追記しないとPreferencesManagerのDart_preferencesが利用できないので注意

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: getFirebaseOptions());
//ここを記載しないとPreferencesManagerの_preferencesが利用できないので注意
  await PreferencesManager().set(await SharedPreferences.getInstance());
  runApp(const ProviderScope(child: MyApp()));
}

利用した感想

ローカルで値を保持することができるSharedPreferencesはすごい!
今までチーム開発で利用されているのは知っていたが利用方法はあまり理解できてなかった...
再度個人で利用するとより理解度が深まりますね
DartdocIdを保存しログインしたユーザーのデータを取得するなどの利用方法もできそうです

より理解するために

より深く理解されたい方はこちらの方の記事が詳しく説明してあってわかりやすいので参考にされてください。
https://virment.com/how-to-use-shared-preferences-in-flutter/

Discussion

JboyHashimotoJboyHashimoto

FirebaseAuthenticationを使うなら、authStateChangeを使えばログイン状態を維持できるので、SharedPreferencesは必要ないそうです。以前はつかわれていたようですが?
バックエンドのAPIを使ったJWT認証のような、Webトークンなるものを保存する目的で、こちらの方法を使うのが一般的だそうです。
以前は、こんな記事なかったので、良い内容だとは思いますね。