Подтвердить что ты не робот

Android: простой счетчик времени

У меня есть простая программа с одним TextView и двумя кнопками: 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);

Я знаю, что есть некоторые подобные вопросы об использовании Thread, но похоже, что они не упоминают об остановке счетчика.

Любое предложение действительно оценено.

Добавлено:

Здравствуйте, я просто сократил свой код только до этого из гораздо более крупной программы, но он все еще разбился:

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)
4b9b3361

Ответ 1

Вы можете ввести флаг. Что-то вроде 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();
 }

Ответ 3

Идеальное решение, если вы хотите отображать текущие часы.

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();
}

Ответ 4

Павел находится на правильном пути, останавливая его, за исключением того, что его ответ пустой, поскольку он не останавливает таймер. Сделайте это в той части, которую он разместил с добавленным выражением else:

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

О, и ты сказал, что он разбился. Мы не знаем, почему это сбой, поэтому, к сожалению, мы не можем помочь понять, почему это делается, если мы не увидим больше кода и ошибки.

Хороший catch @yorkw Проблема, очевидно, связана с чем-то, что она пытается сделать, когда начинает работать. Поскольку он говорит "Таймер-0", это означает, что он никогда не начинается официально, и он застревает в этой части. Первое правило выполнения потоков, НИКОГДА НЕ ИЗМЕНЯЙТЕ ЭЛЕМЕНТЫ UI ИЗ ВНЕШНЕГО интерфейса.. Я бы предложил использовать runOnUiThread, как сказал йорк. Здесь ссылка о том, как ее использовать: runOnUiThread. Довольно уверен, что TimerTask - это runnable, означающее, что он работает в отдельном потоке. Меньше всего то, что я заметил в документах.

Ответ 5

Таким образом, это намного проще. Эта функция доступна на сайте разработчиков 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();
}

Ответ 6

Как подсказал @hovanessyan: вы можете использовать класс Chronometer. Например, следующим образом (с 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" [...]/>
[...]