flutter_hooksのHookWidgetで状態管理を行い、ストップウォッチを作ってみた!
今回使うパッケージ
https://pub.dev/packages/flutter_hooks
これがソースコード
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class StopWatch extends HookWidget {
const StopWatch({super.key});
@override
Widget build(BuildContext context) {
final timer = useState<Stopwatch?>(null);
final elapsedTime = useState<Duration>(Duration.zero);
useEffect(() {
Timer.periodic(const Duration(seconds: 1), (Timer t) {
if (timer.value?.isRunning ?? false) {
elapsedTime.value = elapsedTime.value + const Duration(seconds: 1);
}
});
return null; // useEffectのクリーンアップは不要なのでnullを返す
}, []);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
elapsedTime.value.toString().split('.').first.padLeft(8, "0"),
style: TextStyle(fontSize: 24),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
if (timer.value == null) {
timer.value = Stopwatch()..start();
} else {
timer.value?.start();
}
},
child: Text("開始"),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () {
timer.value?.stop();
},
child: Text("一時停止"),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () {
timer.value?.stop();
elapsedTime.value = Duration.zero;
timer.value = null;
},
child: const Text("完了"),
),
],
)
],
),
),
);
}
}
機能について解説
Dartの標準機能役割について解説
final timer = useState<Stopwatch?>(null);
この行では、現在のStopwatch
インスタンスを保持するためのuseState
を使用しています。初期値はnull
で、これはストップウォッチが開始されるまでのデフォルトの状態を示しています。
final elapsedTime = useState<Duration>(Duration.zero);
elapsedTime
は、ストップウォッチが記録した経過時間を保持するためのuseState
です。初期値はDuration.zero
(0秒)です。
useEffect(() {
Timer.periodic(Duration(seconds: 1), (Timer t) {
if (timer.value?.isRunning ?? false) {
elapsedTime.value = elapsedTime.value + Duration(seconds: 1);
}
});
return null;
}, []);
useEffect
を使用して、コンポーネントのマウント時に1秒ごとに実行されるタイマーを設定しています。このタイマーは、Stopwatch
が動作している場合(timer.value?.isRunning
がtrue
)、elapsedTime
の値を1秒ずつ増加させます。このフックはコンポーネントがマウントされたときにのみ実行されるので、配列の依存関係は空です。
ElevatedButton(
onPressed: () {
if (timer.value == null) {
timer.value = Stopwatch()..start();
} else {
timer.value?.start();
}
},
child: Text("開始"),
),
開始ボタンのonPressed
コールバックです。もしストップウォッチがまだ開始されていない場合(timer.value
がnull
)、新しいStopwatch
インスタンスを作成し、それを開始します。既に存在するStopwatch
がある場合は、それを再開します。
ElevatedButton(
onPressed: () {
timer.value?.stop();
},
child: Text("一時停止"),
),
一時停止ボタンのonPressed
コールバックです。ここで、ストップウォッチのstop
メソッドを呼び出しています。これにより、ストップウォッチは一時停止されます。
ElevatedButton(
onPressed: () {
timer.value?.stop();
elapsedTime.value = Duration.zero;
timer.value = null;
},
child: Text("完了"),
),
完了ボタンのonPressed
コールバックです。ここでは、まずストップウォッチを停止し、次にelapsedTime
を0にリセットし、最後にストップウォッチインスタンス自体をnull
にリセットしています。これにより、完全に初期の状態に戻ります。
最後に
以上が、flutter_hooks
を使用して、ストップウォッチの基本的な機能を実装したソースコードと解説でした。