Riverpod_sample
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:photoapp/photo_list_screen.dart';
import 'package:photoapp/providers.dart';
import 'package:photoapp/sign_in_screen.dart';
// 更新可能なデータを渡したいときに使う
final stateProvider = StateProvider((ref) {
return 0;
});
// Streamをデータとして渡したいときに使う
// ※ autoDisposeを付けると自動的にデータを破棄してくれる
final streamProvider = StreamProvider.autoDispose((ref) {
return FirebaseFirestore.instance.collection('samples').snapshots();
});
// 状況に応じて渡すデータを切り替えたいときに使う
final scopedProvider = ScopedProvider<int>(null);
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
// Providerで定義したデータを渡せるようにする
ProviderScope(
child: MaterialApp(
home: MyWidget(),
),
),
);
}
// ConsumerWidgetを継承すると、
// build()からデータを受け取るためのScopedReaderが提供される
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
// watch()の引数にProviderを指定することで、そのProviderのデータが受け取れる
// また、データが更新された時は自動的に反映される
final int state = watch(stateProvider).state;
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton(
onPressed: () {
// ボタンをタップした時など、context.read()で、その時点のデータを受け取れる
// また、StateProviderは.stateに再代入することでデータを更新できる
context.read(stateProvider).state += 1;
},
child: Text('COUNT: $state'),
),
// Consumerを使うと、
// コールバックからデータを受け取るためのScopedReaderが提供される
Consumer(
builder: (context, ScopedReader watch, child) {
final asyncStream = watch(streamProvider);
// StreamProviderからデータを受け取った時は、
// .when()で状態に応じた処理を行うことができる
return asyncStream.when(
// データの読み込みが完了している場合
data: (QuerySnapshot<Map<String, dynamic>> data) {
return Column(
mainAxisSize: MainAxisSize.min,
children: data.docs.map((doc) {
return Text(doc.get('value') as String);
}).toList(),
);
},
// データが読込中である場合
loading: () {
return CircularProgressIndicator();
},
// データの読み込みに失敗した場合
error: (e, stackTrace) {
return Text(e.toString());
},
);
},
),
// ProviderScopeを使うとProviderで渡すデータを上書きできる
ProviderScope(
overrides: [
// 2倍したデータを渡す
scopedProvider.overrideWithValue(state * 2),
],
child: OtherWidget(),
),
ProviderScope(
overrides: [
// 10倍したデータを渡す
scopedProvider.overrideWithValue(state * 10),
],
child: OtherWidget(),
),
],
),
),
);
}
}
class OtherWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
// 同時に2箇所でOtherWidgetが使われているが、
// ScopedProviderを使うと渡すデータを切り分けられる
final scoped = watch(scopedProvider);
return Text('$scoped');
}
}