今回記事にしたこと
最近、Flutterの学習をしているのですが、ボタンタップ時の非同期処理(API通信)の仕方がわからかったため、調べてみました。
環境
flutter 3.3.9
flutter_riverpod: 2.1.1
Riverpod
公式ドキュメント
https://riverpod.dev/ja/docs/getting_started
簡単にいうと状態管理を容易するためのパッケージ。です。
検索すると多くの記事がヒットすると思うので説明は割愛させて頂きます。
今回作成したもの
ログイン画面を作成しました。
以下の流れを想定しています。
- メールアドレスとパスワードを入力する。
- ログインボタンを押下する。
- ログインAPIを実行する。
- ログインAPIの結果(bool)を受け取り、次の画面に遷移する。
具体的な実装
Userクラス
メールアドレスとパスワードを持ったUserクラスを作成します。
@freezed
class User with _$User {
const factory User({required String mailAddress, required String password}) =
_User;
}
StateNotifier
RiverpodのStateNotifierを使用し、ログインしているかどうかの状態を持つLoginNotifierを作成します。
このクラスにログインメソッド、ログアウトメソッドなどを載せてます。
実際にAPIを実行するのではなく、それっぽく見せるため3秒ほど遅延処理を追加してます。
class LoginNotifier extends StateNotifier<bool> {
LoginNotifier() : super(false);
Future<void> login(User user) async {
state = await Future.delayed(
const Duration(seconds: 3),
() => true,
);
}
Future<void> logout() async {
state = false;
}
}
StateNotifierProvider
LoginNotifierの状態をpublicで公開するStateNotifierProviderを作成します。
final loginProvider = StateNotifierProvider<LoginNotifier, bool>((ref) {
return LoginNotifier();
});
LoginWidget
ログインボタンタップ時の処理に以下を追加する。
ここで先ほど書いたログインメソッドを実行してます。
final user = User(mailAddress: 'email', password: 'password');
ref.read(loginProvider.notifier).login(user);
ref.listen
で状態の監視が可能です。
LoginNotifierの状態が変更された場合は以下の処理が実行されます。
successにログイン結果のboolが格納されており、その値がtrue
の場合にLoginResult画面に遷移します。
class Login extends ConsumerWidget {
const Login({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
...
ref.listen<bool>(loginProvider, (_, success) {
if (success) {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const LoginResult()));
}
});
...
まとめ
FlutterとRiverpodで非同期処理(API通信)の実装の仕方を調べてみました。
他にも色々とやり方はあるのかなとは思いますが、とりあえず実現できました。