27

1つのTextViewと2つのボタン(Button1とButton2)を備えた単純なプログラムがあります。

ボタン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)
4

6 に答える 6

43

旗を紹介できます。のようなもの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();
 }
于 2012-07-30T23:06:01.300 に答える
8

クロノメータークラスを使用するこの例をチェックアウトします: http : //android-er.blogspot.com/2010/06/android-chronometer.html

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

于 2012-07-30T23:06:13.327 に答える
4

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

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();
}
于 2017-10-12T09:35:58.197 に答える
4

このように、それははるかに簡単です。これは、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();
}

Kotlinバージョン

fun initCountDownTimer(time: Int) {
object : CountDownTimer(30000, 1000) {
    override fun onTick(millisUntilFinished: Long) {
        textView.setText("seconds remaining: " + millisUntilFinished / 1000)
    }

    override fun onFinish() {
        textView.setText("done!")
    }
}.start()

}

于 2019-06-26T01:04:17.407 に答える
2

Pavelは、タイマーを停止しないため、彼の答えが無駄であることを除いて、停止することで正しい方向に進んでいます。追加されたelseステートメントで彼が投稿した部分でこれを行います。

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

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

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

于 2012-07-30T23:11:00.587 に答える
1

@hovanessyan提案したように:クロノメータークラスを使用できます。例:次のように(Kotlin、Javaアナログを使用):

class ChronometerToggler: Fragment() {
    private lateinit var chronometer: Chronometer
    private var isChronometerRunning = false
    private lateinit var toggleButton: FloatingActionButton

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.my_layout, container, false)
        chronometer = view.findViewById(R.id.chronometer)
        toggleButton = view.findViewById(R.id.toggle_button)
        toggleButton.setOnClickListener {
            onToggleButtonPressed()
        }
        return view
    }

    private fun onToggleButtonPressed() {
        isChronometerRunning = !isChronometerRunning
        if (isChronometerRunning) {
            chronometer.base = SystemClock.elapsedRealtime()
            chronometer.start()
        }
        else {
            chronometer.stop()
        }
    }
}

my_layout.xml

[...]
     <Chronometer android:id="@+id/chronometer" [...]/>
[...]
于 2019-09-26T13:20:22.430 に答える