[Flutter] タイマーの実装方法
前回はRiverpodを使用して、BottomNavigationBarの実装を行いました。
そして今回はこのBottomNavigationBarを実装をしたプロジェクトにて、「タイマー」 の実装を行います。完成図 |
---|
![]() |
開発version
Flutter version 3.3.2
Dart version 2.18.1
使用するプロバイダー Riverpod
全体コード
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:prefectures47/riverpod/cooperation_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class PageWidget1 extends ConsumerStatefulWidget {
const PageWidget1({Key? key}) : super(key: key);
_PageWidget1State createState() => _PageWidget1State();
}
class _PageWidget1State extends ConsumerState<PageWidget1> {
DateTime? _createTime;
Timer? _timer;
void initState() {
super.initState(); // initState 関数の実装は、super.initState を呼び出して開始する必要があります。
_createTime = DateTime.now(); //変数_createTimeにDateTime.nowを代入
_startTimer();
}
// タイマーのスタート
void _startTimer() {
final createTime = _createTime!.add(const Duration(minutes: 1)); // タイマーの時間
_timer = Timer.periodic(const Duration(milliseconds: 10), (timer) {
final remain = createTime.difference(DateTime.now());
if (remain > Duration.zero) {
ref.read(cooperationTimerProvider.state).state =
remain.inMilliseconds; //タイマーが動く
}
});
}
Widget build(BuildContext context) {
final timer = ref.watch(cooperationTimerProvider);
final displayTime =
Duration(milliseconds: timer).toString().substring(2, 10); // ミリ秒設定
// 作成した時間
final createTime = DateFormat('yyyy/MM/dd/HH:mm').format(_createTime!);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('残り時間'),
SizedBox(width: 10),
Text('$displayTime'),
],
),
SizedBox(height: 20),
Text('$createTime'),
],
));
}
}
型、変数
DateTime? _createTime;
Timer? _timer;
DateTime型に_createTime変数を、Timer型には_timer変数と宣言します。
関数
void initState() {
super.initState();
_createTime = DateTime.now();
_startTimer();
}
initState の実装は、super.initState を呼び出して開始する必要があります。
なぜsuper.initStateが必要かどうか下記のリンクに書いてあります(正直私は理解できておりません)
_createTimeにDateTime.nowを代入します。
最後にタイマーをスタートさせる関数、_startTimerを用意します。
タイマーの関数
void _startTimer() {
final createTime = _createTime!.add(const Duration(minutes: 1)); // タイマーの時間
_timer = Timer.periodic(const Duration(milliseconds: 10), (timer) {
final remain = createTime.difference(DateTime.now());
if (remain > Duration.zero) {
ref.read(cooperationTimerProvider.state).state =
remain.inMilliseconds; //タイマーが動く
}
});
}
_startTimer() と言う関数用意しました。
さてここから長くなりますが、自分なりに解説していこうと思います。
タイマーの時間
final createTime = _createTime!.add(const Duration(minutes: 1)); // タイマーの時間
_createTime!にadd.メソッドを追加します。これは後に続く(const Duration(minutes: 1));と関わがあります。
次にDurationクラスを用意します。
Durationクラスには時間単位を表示させるプロパティが存在します、詳しくは下記の記事を読んでみてください。(今回はminutesと言う「分」を取得できるプロパティを使用します)
ミリ秒を取得する(milliseconds)
_timer = Timer.periodic(const Duration(milliseconds: 10), (timer)
続いては変数で用意した_timer変数を使います。
_timer変数にTimer.periodic(const Duration(milliseconds: 10)を代入させます。このperiodic関数は毎x秒後に繰り返し実行するメソッドです。詳しくは下記の記事に書いてあるので読んでみてください。
DateTimeから差分を時間で取得する(differenceメソッド)
final remain = createTime.difference(DateTime.now());
remain変数に、DateTimeから差分を代入します。
DateTimeから差分を時間で取得するには、differenceメソッドを使用します。下記公式記事を参考にしてください。
differenceメソッドの引数にはDateTime.now()を入れます。
タイマーが動く箇所
if (remain > Duration.zero) {
ref.read(cooperationTimerProvider.state).state =
remain.inMilliseconds; //タイマーが動く
}
if文を使用し「remain変数がDuration.zeroより大きいならタイマーが動く」と記述します。
必然的にゼロより大きい数になるのでRiverpodの中身が動きます。
final cooperationTimerProvider = StateProvider<int>((ref) => 0);
View側の全体コード
Widget build(BuildContext context) {
final timer = ref.watch(cooperationTimerProvider);
final displayTime =
Duration(milliseconds: timer).toString().substring(2, 10); // ミリ秒設定
// 作成した時間
final createTime = DateFormat('yyyy/MM/dd/HH:mm').format(_createTime!);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('残り時間'),
SizedBox(width: 10),
Text('$displayTime'),
],
),
SizedBox(height: 20),
Text('$createTime'),
],
));
}
}
残り時間を取得する
final timer = ref.watch(cooperationTimerProvider);
final displayTime =
Duration(milliseconds: timer).toString().substring(2, 10); // ミリ秒設定
プロバイダーから時間を取得し、取得したtimerをDurationの引数に当てます。
substring(2, 10)にはミリ秒設定を行います。
作成した時間設定
final createTime = DateFormat('yyyy/MM/dd/HH:mm').format(_createTime!);
残り時間と作成した時間を配置
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('残り時間'),
SizedBox(width: 10),
Text('$displayTime'),
],
),
SizedBox(height: 20),
Text('$createTime'),
],
));
さて最後です。
変数を配置したら、タイマーの完成です。お疲れ様でした!
終わりに
いかがでしょうか?
本業にてクーポンを使用する挙動の処理に携わったのて、「クーポンを使用したら、タイマーのカウントが始まる」
と言う少しマイナーなところを記事にしてみました(笑)
Discussion
残り時間と作成した時間を配置しましょう!の下の
が、r抜けてた!
return になるはず!
僕もよくタイポしますけどね😅
Jboyさんありがとうございます!修正します!
私が、意見して良いものかと思いましたが(^^!)
チケットのロジック面白かったです!