main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'dart:async'; // Timerに必要
import 'package:intl/intl.dart'; // 日付フォーマットに必要
// 1. 1秒ごとに現在時刻をStreamで流すProvider
final dateTimeStreamProvider = StreamProvider((ref) {
// periodicは指定したDurationごとに処理を実行する
return Stream.periodic(const Duration(seconds: 1), (_) => DateTime.now())
.startWith(DateTime.now()); // 最初の一回は即座に時間を表示
});
void main() {
runApp(
// Riverpodを利用するためにProviderScopeで囲む
const ProviderScope(child: MyApp()),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ClockScreen(),
);
}
}
class ClockScreen extends ConsumerWidget {
const ClockScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 2. ProviderをWatchする
final asyncDateTime = ref.watch(dateTimeStreamProvider);
return Scaffold(
appBar: AppBar(title: const Text('Riverpod 現在時刻')),
body: Center(
child: asyncDateTime.when(
data: (dateTime) {
// 3. 日付と時刻のフォーマット
final dateStr = DateFormat('yyyy年MM月dd日 (E)').format(dateTime);
final timeStr = DateFormat('HH:mm:ss').format(dateTime);
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(dateStr, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 10),
Text(timeStr, style: const TextStyle(fontSize: 48, fontWeight: FontWeight.bold)),
],
);
},
loading: () => const CircularProgressIndicator(),
error: (error, stack) => Text('Error: $error'),
),
),
);
}
}
// Streamの最初の読み込みをスキップしないための拡張機能
extension StreamExtension on Stream {
Stream startWith(T value) {
return Stream.multi((controller) {
controller.add(value);
this.listen(controller.add);
});
}
}