web-dev-qa-db-ja.com

Android:シンプルな時間カウンター

TextViewが1つとButton1とButton2の2つのボタンがある単純なプログラムがあります。

ボタン1をクリックすると、カウンターが開始され、1秒ごとに1ずつ増加し、TextViewに結果が表示されます。ボタン2をクリックすると停止します。 Button1のコードの一部を次に示します。しかし、それは機能しません。

    Timer T=new Timer();
    T.scheduleAtFixedRate(new TimerTask() {         
            @Override
            public void run() {
                myTextView.setText("count="+count);
                count++;                
            }
        }, 1000, 1000);

スレッドを使用してこれについて同様の質問があることを知っていますが、カウンターの停止については言及していないようです。

どんな提案も本当に感謝しています。

追加:

こんにちは、はるかに大きなプログラムからこれにコードを短縮しましたが、まだクラッシュしています:

package com.example.hello;
import Java.util.Timer;
import Java.util.TimerTask;
import Android.os.Bundle;
import Android.app.Activity;
import Android.view.Menu;
import Android.widget.TextView;
public class MainActivity extends Activity {
    TextView myTextView;
    int count=0;
    Timer T;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myTextView=(TextView)findViewById(R.id.t);
        T=new Timer();
        T.scheduleAtFixedRate(new TimerTask() {         
            @Override
            public void run() {
                myTextView.setText("count="+count);
                count++;                
            }
        }, 1000, 1000);       
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}

ログファイル(長すぎるので誰かが要求したため、これを投稿したくない):

07-28 17:35:07.012: W/dalvikvm(11331): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
07-28 17:35:07.016: E/AndroidRuntime(11331): FATAL EXCEPTION: Timer-0
07-28 17:35:07.016: E/AndroidRuntime(11331): Android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.ViewRoot.checkThread(ViewRoot.Java:2802)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.ViewRoot.requestLayout(ViewRoot.Java:594)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.widget.RelativeLayout.requestLayout(RelativeLayout.Java:254)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.view.View.requestLayout(View.Java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.widget.TextView.checkForRelayout(TextView.Java:5378)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.widget.TextView.setText(TextView.Java:2688)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.widget.TextView.setText(TextView.Java:2556)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Android.widget.TextView.setText(TextView.Java:2531)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at com.example.hello.MainActivity$1.run(MainActivity.Java:21)
07-28 17:35:07.016: E/AndroidRuntime(11331):    at Java.util.Timer$TimerImpl.run(Timer.Java:289)
21
DavidNg

フラグを導入できます。 isPausedのようなもの。 「一時停止」ボタンが押されるたびにこのフラグをトリガーします。タイマータスクのフラグ値を確認します。成功。

Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {         
        @Override
        public void run() {
            runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    myTextView.setText("count="+count);
                    count++;                
                }
            });
        }
    }, 1000, 1000);


 onClick(View v)
 {
      //this is 'Pause' button click listener
      T.cancel();
 }
36
Pavel Dudka

Chekout this の例、 Chronometer クラスを使用: http://Android-er.blogspot.com/2010/06/Android-chronometer.html

Chronometerクラスを使用すると、スレッドを自分で管理する手間が省けます。

6
hovanessyan

ランニングクロックを表示する場合に最適なソリューションです。

private void startClock(){
    Thread t = new Thread() {

        @Override
        public void run() {
            try {
                while (!isInterrupted()) {
                    Thread.sleep(1000);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Calendar c = Calendar.getInstance();

                            int hours = c.get(Calendar.HOUR_OF_DAY);
                            int minutes = c.get(Calendar.MINUTE);
                            int seconds = c.get(Calendar.SECOND);

                            String curTime = String.format("%02d  %02d  %02d", hours, minutes, seconds);
                            clock.setText(curTime); //change clock to your textview
                        }
                    });
                }
            } catch (InterruptedException e) {
            }
        }
    };

    t.start();
}
3

Pavelはそれを停止することで正しい軌道に乗っていますが、彼の答えはタイマーを停止しないため無駄です。彼が追加したelseステートメントで投稿した部分でこれを行います。

if(!isPaused)
        {
            myTextView.setText("count="+count);
            count++;                
        } else {
            cancel();//adding this makes it actually stop
        }

ああ、あなたはそれがクラッシュしたと言いました。なぜクラッシュするのかわからないので、残念ながら、コードとエラーが表示されない限り、なぜクラッシュするのかを理解することはできません。

良いキャッチ@yorkw問題は明らかに、実行が開始されたときに何をしようとしているかにあります。 「Timer-0」と表示されているため、これは公式には開始せず、その部分で停止することを意味します。スレッドを実行する最初のルール、UIの外部からUI要素を変更しないでください。 yorkが言ったようにrunOnUiThreadを使用することをお勧めします。使用方法に関するリンクを次に示します。 runOnUiThreadTimerTaskが実行可能であることを確認してください。つまり、別のスレッドで実行されます。少なくともそれは私がドキュメントで気づいたことです。

2
Andy

この方法では、はるかに簡単です。これは、Android開発者サイト。 リンク

public void initCountDownTimer(int time) {
    new CountDownTimer(30000, 1000) {

        public void onTick(long millisUntilFinished) {
            textView.setText("seconds remaining: " + millisUntilFinished / 1000);
        }

        public void onFinish() {
            textView.setText("done!");
        }
    }.start();
}