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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

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

Q&A

解決済

2回答

1802閲覧

[Android] HandlerとLooperによるループ処理が遅れる(ストップウォッチのカウントがうまく行きません)

holly0819

総合スコア17

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

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

0グッド

0クリップ

投稿2021/02/02 02:37

前提・実現したいこと

Android Studioでストップウォッチを作っています。

発生している問題・エラーメッセージ

HandlerとLooperによるループ処理を使って10ミリ秒単位でカウントさせたいのですが、約2倍ほど遅れてしまいます。

100ミリ秒単位でカウントさせるとうまく動作しました。なぜ10ミリ秒だとうまく行かないのでしょうか?

該当のソースコード

Java

1// import文、質問と関係ない箇所は省略しています。 2 3public class MainActivity extends AppCompatActivity { 4 5 private static Boolean isActive = false; 6 private Button playButton; 7 private TextView timerText; 8 private int time = 0; 9 private final SimpleDateFormat dateFormat = new SimpleDateFormat("mm:ss:SS"); 10 11 private final Handler handler = new Handler(Looper.getMainLooper()); 12 private final Runnable runnable = new Runnable() { 13 @Override 14 public void run() { 15 time ++; 16 // ここの"10"を"100"に変えると正常に動作します。 17 timerText.setText(dateFormat.format(time * 10)); 18 handler.postDelayed(this, 10); 19 } 20 }; 21 22 @Override 23 protected void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_main); 26 27 playButton = findViewById(R.id.playButton); 28 timerText = findViewById(R.id.timer); 29 } 30 31 public void startTimer(View view) { 32 if(!isActive) { 33 isActive = true; 34 handler.post(runnable); 35 36 // backgroundとonclickを停止ボタンのものにする 37 playButton.setBackground(getResources().getDrawable(R.drawable.stop_button)); 38 playButton.setOnClickListener(this::stopTimer); 39 } 40 } 41 42 public void stopTimer(View view) { 43 if(isActive) { 44 isActive = false; 45 handler.removeCallbacks(runnable); 46 47 // backgroundとonclickをスタートボタンのものにする 48 playButton.setBackground(getResources().getDrawable(R.drawable.play_button)); 49 playButton.setOnClickListener(this::startTimer); 50 } 51 } 52}

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

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

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

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

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

guest

回答2

0

ベストアンサー

https://stackoverflow.com/questions/51383626/handler-not-running-1000-times-in-1-second

stackoverflowの回答にヒントがありました。

"Returns the current time in milliseconds. Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds."
「現在の時刻をミリ秒単位で返します。 戻り値の時間の単位はミリ秒ですが、値の粒度は基盤となるオペレーティングシステムによって異なり、それよりも大きくなる場合があることに注意してください。 たとえば、多くのオペレーティングシステムは、数十ミリ秒の単位で時間を測定します。」

10ミリ秒単位で測るのはシステム的に厳しいようです。

投稿2021/02/02 03:11

ppin

総合スコア58

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

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

holly0819

2021/02/02 04:40

回答ありがとうございます。 カウントの方法を変えた方が良さそうですね。 ループ前にミリ秒単位で時刻を取得して、前回のループの時刻との差分をtimeに加算する方法に変えたらうまく行きました。
guest

0

ループ前にミリ秒単位で時刻を取得して、前回のループの時刻との差分をtimeに加算する方法に変えたところ、うまく行きました。
回答された方ありがとうございました。

// 変更前 private final Runnable runnable = new Runnable() { @Override public void run() { time ++; timerText.setText(dateFormat.format(time * 10)); handler.postDelayed(this, 10); } };
// 変更後 // タイマーを止めるときはcurrentTimeとbeforeTimeを0にします。 private final Runnable runnable = new Runnable() { @Override public void run() { currentTime = System.currentTimeMillis(); if(beforeTime > 0) { time += currentTime - beforeTime; } timerText.setText(dateFormat.format(time)); beforeTime = currentTime; handler.postDelayed(this, interval); } };

投稿2021/02/02 04:44

holly0819

総合スコア17

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問