質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

1回答

1770閲覧

【Flutter】スマホアプリでストップウォッチを作っているが、1000分の1秒の誤差が発生してしまう

ametyan

総合スコア43

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2020/09/06 18:48

編集2022/01/12 10:55

Flutterを使ってスマホアプリでストップウォッチを作っており、お試しとして500ミリ秒ずつ経過時間を画面に表示することにしました。
すると経過時間に1000分の1秒の誤差が発生してしまいます。時々100分の1秒の誤差も発生します。
下記画像ですと6ミリ秒の誤差が発生しています。
この誤差をなくすテクニックはありますか?

イメージ説明

main.dart

Dart

1import 'package:flutter/material.dart'; 2import 'time.dart'; 3import 'button.dart'; 4 5void main() { 6 runApp(MyApp()); 7} 8 9class MyApp extends StatelessWidget { 10 11 Widget build(BuildContext context) { 12 return MaterialApp( 13 title: 'タイトルですよ', 14 home: Scaffold( 15 appBar: AppBar( 16 title: Text('appBarですよ'), 17 ), 18 body: Center( 19 child: Column( 20 mainAxisSize: MainAxisSize.min, 21 children: <Widget>[ 22 Padding( 23 padding: EdgeInsets.all(50.0), 24 child: Clock(), 25 ), 26 MyButton(), 27 ], 28 ))), 29 ); 30 } 31} 32

button.dart

Dart

1import 'package:flutter/material.dart'; 2 3class MyButton extends StatefulWidget { 4 5 _MyButtonState createState() => _MyButtonState(); 6} 7 8class _MyButtonState extends State<MyButton> { 9 bool _pressAttention = true; 10 11 void _pressButton() { 12 setState(() { 13 _pressAttention = !_pressAttention; 14 }); 15 } 16 17 18 Widget build(BuildContext context) { 19 return ButtonTheme( 20 minWidth: 100.0, 21 height: 100.0, 22 child: RaisedButton( 23 onPressed: _pressButton, 24 child: _pressAttention ? Text('Start', style: TextStyle(fontSize: 30.0),) : Text('Stop', style: TextStyle(fontSize: 30.0),), 25 color: _pressAttention ? Colors.blue : Colors.red, 26 shape: CircleBorder( 27 side: BorderSide( 28 color: Colors.black, 29 width: 1.0, 30 style: BorderStyle.solid, 31 ), 32 ), 33 )); 34 } 35}

time.dart

Dart

1import 'package:flutter/material.dart'; 2import 'package:intl/intl.dart'; 3import 'dart:async'; 4 5class Clock extends StatefulWidget { 6 7 State<StatefulWidget> createState() { 8 return _ClockState(); 9 } 10} 11 12class _ClockState extends State<Clock> { 13 Stopwatch s = Stopwatch(); 14 String _time = ''; 15 16 17 void initState() { 18 s.start(); 19 Timer.periodic( 20 Duration(milliseconds: 500), 21 _onTimer, 22 ); 23 super.initState(); 24 } 25 26 void _onTimer(Timer timer) { 27 setState(() => _time = '${s.elapsedMilliseconds}'); 28 } 29 30 31 Widget build(BuildContext context) { 32 return Text( 33 _time, 34 style: TextStyle(fontSize: 30.0), 35 ); 36 } 37}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

少し調べたところTimer.periodicの実装は割と曖昧で、1ms単位で正確に処理を行うのは難しいのかもしれません。
参考までに、公式ドキュメントにも以下のような記述があります。

the time between two consecutive callbacks can be shorter and longer than duration.

また、タイマーを使ったサンプルコードもいくつか確認しましたが、
すべて以下のように、1000分の1秒単位は切り捨てる実装になっていました。

dart

1transformMilliSecondsToString(int milliseconds) { 2 int hundreds = (milliseconds / 10).truncate(); 3 int seconds = (hundreds / 100).truncate(); 4 int minutes = (seconds / 60).truncate(); 5 int hours = (minutes / 60).truncate(); 6 7 String hundredsStr = (hundreds % 100).toString().padLeft(2, '0'); 8 String secondsStr = (seconds % 60).toString().padLeft(2, '0'); 9 String minutesStr = (minutes % 60).toString().padLeft(2, '0'); 10 String hoursStr = (hours % 60).toString().padLeft(2, '0'); 11 12 return '$hoursStr : $minutesStr : $secondsStr.$hundredsStr'; 13}

参考 :

投稿2020/09/07 08:44

nskhei

総合スコア704

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ametyan

2020/09/07 12:50

調べていただきありがとうございます! 1ms単位での処理は難しいのですね。承知しました。 ちなみに、Dart以外の言語で1msの処理が可能な言語などご存知でしたら、教えていただきたいです。 世に出回っている1ms単位の処理をするアプリがどのように実現しているのかを知りたいです。
nskhei

2020/09/07 15:07 編集

いえいえ、こちらこそとても良い勉強になりました! 他言語については分かりませんが、調べたところ1msというのはかなりの高精度なので、簡単ではないかもしれません。 あと、端末自体の性能にも左右されると思います。 個人的な予想ですが、世に出回っているアプリでは1ms単位の誤差は丸めて表示しているか、毎回誤差を補正するようなアルゴリズムが使われているのではないかと思います。 例えば、6msの誤差が出たら、次の処理は494ms後に設定するみたいな感じです。 この辺参考にしてみて下さい。 ・https://qiita.com/jkr_2255/items/fe72a451d1fc4fa81ba3https://rksoftware.hatenablog.com/entry/2018/01/22/014229https://nagise.hatenablog.jp/entry/20110221/1298301239https://ja.stackoverflow.com/questions/5576/mfc
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問