📌
asData propertyとは?
⚙️riverpodの機能らしい?
AsyncData<T>?asData
AsyncValueをAsyncDataにアップキャストするか、AsyncValueがAsyncLoading/AsyncErrorの場合はnullを返します。
AsyncDataは、プルツーリフレッシュ中など、まだロード/エラー状態にある可能性があることに注意してください。
go router builder
でredirect
の処理を実装したかったが上手くいかなかった???
FirebaseAuthの認証の情報を取得する必要があったので、riverpodのasData
を使用した。
動作はこんな感じになってます
ソースコードはこんな感じです。riverpodのプロバイダーで囲んでおく必要があります。出ないと、StreamProviderを呼び出せないです。
認証用のプロバイダー
import 'package:firebase_auth/firebase_auth.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
// Firebase Authenticationのインスタンスを生成するプロバイダー
final firebaseAuthProvider = Provider((ref) => FirebaseAuth.instance);
// ログイン状態を監視するプロバイダー
final authStateProvider = StreamProvider((ref) {
return ref.watch(firebaseAuthProvider).authStateChanges();
});
go router builder
にredirect
の処理を組み込んだコード
👤router.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:value_notifier_example/ui/page/first_page.dart';
import '../../provider/auth_provider.dart';
import '../../ui/page/next_page.dart';
part 'router.g.dart';
// ファイルを自動生成するときは、下のコマンドを実行する.
// flutter pub run build_runner build --delete-conflicting-outputs
final routerProvider = Provider((ref) {
final authState = ref.watch(authStateProvider);
return GoRouter(
debugLogDiagnostics: true,
routes: $appRoutes,// 自動生成されたファイルからパスを読み込む
// リダイレクトの処理
redirect: (BuildContext context, GoRouterState state) {
// asData?.valueは、riverpodのStreamProviderの値を取得するプロパティ
final bool loggedIn = authState.asData?.value != null;
// ログインしていない場合は、ログインページにリダイレクトする
if (!loggedIn) {
return const FirstRoute().location;
}
// ログインしている場合は、NextPageにリダイレクトする
return const NextRoute().location;
},
// 404ページを指定
errorPageBuilder: (context, state) {
return const MaterialPage(
child: Scaffold(
body: Center(
child: Text('Page not found'),
),
));
},
);
});
<FirstRoute>(
path: '/',
)
class FirstRoute extends GoRouteData {
const FirstRoute();
Widget build(BuildContext context, GoRouterState state) {
return const FirstPage();
}
}
/// [NextPageのルート]
<NextRoute>(
path: '/next',
)
class NextRoute extends GoRouteData {
const NextRoute();
Widget build(BuildContext context, GoRouterState state) {
return const NextPage();
}
}
⚙️ページを作成
匿名認証を使ってユーザーを登録する画面。登録できたら、リダイレクトの処理が実行され、NextPageへ移動する。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:value_notifier_example/provider/auth_provider.dart';
class FirstPage extends HookConsumerWidget {
const FirstPage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('登録ページ'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: () async {
await ref.read(firebaseAuthProvider).signInAnonymously();
}, child: const Text('登録')),
],
)
),
);
}
}
ログイン後のNextPageのログアウトボタンを押すと、認証状態が、falseになるので、FirstPageへリダイレクトする。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../provider/auth_provider.dart';
class NextPage extends HookConsumerWidget {
const NextPage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('ログイン後のページ'),
),
body: Center(
child: Column(
children: [
ElevatedButton(onPressed: () async {
// ログアウトするメソッド
await ref.read(firebaseAuthProvider).signOut();
}, child: const Text('Go Back')),
],
)
),
);
}
}
main.dartはこんな感じです。
main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:value_notifier_example/firebase_options.dart';
import 'common/router/router.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends HookConsumerWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp.router(
routerConfig: ref.watch(routerProvider),
theme: ThemeData(
primarySwatch: Colors.blue,
),
);
}
}
最後に
今回は、asDataとはどんなものなのかを解説した記事というより、認証機能の記事を書いた感じになってしまいました。
値があれば、castして、データを戻り値として返してくれて、エラーか、ロード中だったら、nullを返すと書かれている解説のように思えました。
Discussion