Como definir o temporizador no android?

325

Alguém pode dar um exemplo simples de atualizar um campo de texto a cada segundo mais ou menos?

Quero fazer uma bola voadora e preciso calcular / atualizar as coordenadas da bola a cada segundo, é por isso que preciso de um temporizador.

Eu não entendo nada daqui .

SERG
fonte
14
Esta classe pode ajudar: developer.android.com/reference/android/os/CountDownTimer.html
Paramvir Singh:
Isso vai ajudar. sampleprogramz.com/android/chronometer.php
Ashokchakravarthi Nagarajan

Respostas:

463

ok, já que isso não foi esclarecido, ainda existem três maneiras simples de lidar com isso. Abaixo está um exemplo mostrando todos os 3 e, na parte inferior, um exemplo mostrando apenas o método que acredito ser preferível. Lembre-se também de limpar suas tarefas no onPause, salvando o estado, se necessário.


import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class main extends Activity {
    TextView text, text2, text3;
    long starttime = 0;
    //this  posts a message to the main thread from our timertask
    //and updates the textfield
   final Handler h = new Handler(new Callback() {

        @Override
        public boolean handleMessage(Message msg) {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text.setText(String.format("%d:%02d", minutes, seconds));
            return false;
        }
    });
   //runs without timer be reposting self
   Handler h2 = new Handler();
   Runnable run = new Runnable() {

        @Override
        public void run() {
           long millis = System.currentTimeMillis() - starttime;
           int seconds = (int) (millis / 1000);
           int minutes = seconds / 60;
           seconds     = seconds % 60;

           text3.setText(String.format("%d:%02d", minutes, seconds));

           h2.postDelayed(this, 500);
        }
    };

   //tells handler to send a message
   class firstTask extends TimerTask {

        @Override
        public void run() {
            h.sendEmptyMessage(0);
        }
   };

   //tells activity to run on ui thread
   class secondTask extends TimerTask {

        @Override
        public void run() {
            main.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                   long millis = System.currentTimeMillis() - starttime;
                   int seconds = (int) (millis / 1000);
                   int minutes = seconds / 60;
                   seconds     = seconds % 60;

                   text2.setText(String.format("%d:%02d", minutes, seconds));
                }
            });
        }
   };


   Timer timer = new Timer();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        text = (TextView)findViewById(R.id.text);
        text2 = (TextView)findViewById(R.id.text2);
        text3 = (TextView)findViewById(R.id.text3);

        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button)v;
                if(b.getText().equals("stop")){
                    timer.cancel();
                    timer.purge();
                    h2.removeCallbacks(run);
                    b.setText("start");
                }else{
                    starttime = System.currentTimeMillis();
                    timer = new Timer();
                    timer.schedule(new firstTask(), 0,500);
                    timer.schedule(new secondTask(),  0,500);
                    h2.postDelayed(run, 0);
                    b.setText("stop");
                }
            }
        });
    }

    @Override
    public void onPause() {
        super.onPause();
        timer.cancel();
        timer.purge();
        h2.removeCallbacks(run);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }
}


o principal a lembrar é que a interface do usuário só pode ser modificada a partir do thread principal da interface do usuário; portanto, use um manipulador ou atividade.runOnUIThread (Runnable r);

Aqui está o que considero o método preferido.


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TestActivity extends Activity {

    TextView timerTextView;
    long startTime = 0;

    //runs without a timer by reposting this handler at the end of the runnable
    Handler timerHandler = new Handler();
    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            long millis = System.currentTimeMillis() - startTime;
            int seconds = (int) (millis / 1000);
            int minutes = seconds / 60;
            seconds = seconds % 60;

            timerTextView.setText(String.format("%d:%02d", minutes, seconds));

            timerHandler.postDelayed(this, 500);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_activity);

        timerTextView = (TextView) findViewById(R.id.timerTextView);

        Button b = (Button) findViewById(R.id.button);
        b.setText("start");
        b.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Button b = (Button) v;
                if (b.getText().equals("stop")) {
                    timerHandler.removeCallbacks(timerRunnable);
                    b.setText("start");
                } else {
                    startTime = System.currentTimeMillis();
                    timerHandler.postDelayed(timerRunnable, 0);
                    b.setText("stop");
                }
            }
        });
    }

  @Override
    public void onPause() {
        super.onPause();
        timerHandler.removeCallbacks(timerRunnable);
        Button b = (Button)findViewById(R.id.button);
        b.setText("start");
    }

}


Dave.B
fonte
1
@ Dave.B, obrigado pelo ótimo exemplo. Existem vantagens / desvantagens em usar um método versus os outros que você descreveu?
Gautam
2
@ Gautam Acredito que todos os métodos acima tenham o mesmo desempenho. Pessoalmente, prefiro o método manipulador descrito acima com a execução Runnable e h2 Handler, pois é o prescrito pelo site do desenvolvedor Android e, na minha opinião, também o mais elegante.
Dave.B
6
Seria bom ter seu método preferido separado do restante do código. Como se você pudesse ter um exemplo mostrando seu caminho preferido e outro mostrando as alternativas. Tendo os três métodos juntos, fica mais difícil entender o que está acontecendo (especialmente para um novato no Android como eu). Provavelmente perguntando demais :)
Jesse Aldridge
4
@JesseAldridge Good idea. Fui em frente e adicionei código apenas com o método preferido.
Dave.B
1
@bluesm Eu honestamente simplesmente não pensei nisso, mas sim, isso funcionaria bem.
precisa saber é o seguinte
84

É simples! Você cria um novo timer.

Timer timer = new Timer();

Então você estende a tarefa do timer

class UpdateBallTask extends TimerTask {
   Ball myBall;

   public void run() {
       //calculate the new position of myBall
   }
}

E adicione a nova tarefa ao Timer com algum intervalo de atualização

final int FPS = 40;
TimerTask updateBall = new UpdateBallTask();
timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS);

Isenção de responsabilidade: Esta não é a solução ideal. Esta é a solução usando a classe Timer (conforme solicitado pelo OP). No Android SDK, é recomendável usar a classe Handler (há um exemplo na resposta aceita).

ficção
fonte
1
se você ler o post acima você vai ver por que isso não é uma solução ideal
Dave.B
2
Claro. O OP queria fazer isso com o TimerTask, que não recomendo que seja usado no jogo.
ficção
3
Hã? O OP não especificou como eles queriam que fosse feito. Eles vincularam a um artigo que usava o TimerTask, mas não pediram que fosse feito dessa maneira.
Página
1
Ajudou muito, obrigado @fiction
Naveed Ahmad
1
ótima resposta simples de seguir.
JMASTER B
64

Se você também precisar executar seu código no thread da interface do usuário (e não no timer), consulte o blog: http://steve.odyfamily.com/?p=12

public class myActivity extends Activity {
private Timer myTimer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);

    myTimer = new Timer();
    myTimer.schedule(new TimerTask() {          
        @Override
        public void run() {
            TimerMethod();
        }

    }, 0, 1000);
}

private void TimerMethod()
{
    //This method is called directly by the timer
    //and runs in the same thread as the timer.

    //We call the method that will work with the UI
    //through the runOnUiThread method.
    this.runOnUiThread(Timer_Tick);
}


private Runnable Timer_Tick = new Runnable() {
    public void run() {

    //This method runs in the same thread as the UI.               

    //Do something to the UI thread here

    }
};
}
Meir Gerenstadt
fonte
Por uma questão de completude, talvez você possa mencionar o que fazer para parar o cronômetro e talvez reiniciá-lo. (Eu encontrei as informações necessárias aqui: stackoverflow.com/questions/11550561/... )
RenniePet
3
Existe algum motivo para você não chamar o runOnUIThread diretamente do método de execução TimerTask? Parece funcionar bem e remove outro nível de aninhamento.
21714 RichieHH
Claro, é apenas um método didático para entender todas as etapas. Sugiro que esse padrão tenha um código legível.
Meir Gerenstadt
41

Se você quiser apenas agendar uma contagem regressiva até um momento no futuro com notificações regulares em intervalos ao longo do caminho, poderá usar a classe CountDownTimer que está disponível desde o nível 1 da API.

new CountDownTimer(30000, 1000) {
    public void onTick(long millisUntilFinished) {
        editText.setText("Seconds remaining: " + millisUntilFinished / 1000);
    }

    public void onFinish() {
        editText.setText("Done");
    }
}.start();
Ahmed Hegazy
fonte
2
O CountDownTimer só faz sentido se você souber que deseja que ele desapareça após várias execuções. Esta não é uma abordagem típica, nem particularmente flexível. Mais comum é o cronômetro que se repete para sempre (que você cancela quando não é mais necessário) ou o manipulador que é executado uma vez e, em seguida, é iniciado novamente se for necessário novamente. Veja outras respostas.
Página
1
Você está totalmente certo. Desde o nome da classe, ele fornece uma contagem decrescente do tempo até o final e, é claro, usa o Handler em sua implementação.
Ahmed Hegazy
Como mostrar milissegundos também? No formato SS:MiMi? Obrigado
Ruchir Baronia
26

Este é um código simples para um timer:

Timer timer = new Timer();
TimerTask t = new TimerTask() {       
    @Override
    public void run() {

        System.out.println("1");
    }
};
timer.scheduleAtFixedRate(t,1000,1000);
Jevgenij Kononov
fonte
12

Eu acho que você pode fazê-lo da maneira Rx, como:

 timerSubscribe = Observable.interval(1, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                      //TODO do your stuff
                }
            });

E cancele isto como:

timerSubscribe.unsubscribe();

Rx Timer http://reactivex.io/documentation/operators/timer.html

Vai
fonte
10

Como essa pergunta ainda está atraindo muitos usuários da pesquisa do Google (sobre o temporizador do Android), gostaria de inserir minhas duas moedas.

Primeiro, a classe Timer será descontinuada no Java 9 (leia a resposta aceita) .

A maneira oficial sugerida é usar o ScheduledThreadPoolExecutor, que é mais eficaz e rico em recursos que pode agendar adicionalmente comandos para serem executados após um determinado atraso ou para serem executados periodicamente. Além disso, oferece flexibilidade e recursos adicionais do ThreadPoolExecutor.

Aqui está um exemplo do uso de funcionalidades simples.

  1. Crie serviço executor:

    final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
  2. Basta agendar sua execução:

    final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
  3. Agora você pode usar future para cancelar a tarefa ou verificar se é feita, por exemplo:

    future.isDone();

Espero que você ache isso útil para criar tarefas no Android.

Exemplo completo:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS);
if (sampleFutureTimer.isDone()){
    // Do something which will save world.
}
szholdiyarov
fonte
8

Estou surpreso que não haja resposta que mencionaria solução com RxJava2 . É realmente simples e fornece uma maneira fácil de configurar o temporizador no Android.

Primeiro, você precisa configurar a dependência do Gradle, se ainda não o fez:

implementation "io.reactivex.rxjava2:rxjava:2.x.y"

(substitua xe ypelo número da versão atual )

Como temos apenas uma tarefa simples, NÃO REPETIDORA , podemos usar o Completableobjeto:

Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(() -> {
            // Timer finished, do something...
        });

Para REPETIR TAREFA , você pode usar de Observablemaneira semelhante:

Observable.interval(2, TimeUnit.SECONDS, Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(tick -> {
            // called every 2 seconds, do something...
        }, throwable -> {
            // handle error
        });

Schedulers.computation() garante que nosso timer esteja em execução no thread de segundo plano e .observeOn(AndroidSchedulers.mainThread()) significa que o código executado após o término do cronômetro será realizado no encadeamento principal.

Para evitar vazamentos indesejados de memória, cancele a inscrição quando a Atividade / Fragmento for destruída.

Micer
fonte
4
Esta é a abordagem mais limpa!
Constantin
como se cancela isso? ou seja, quando o usuário pressiona o botão [STOP] na interface do usuário e o Completable é cancelado antes de executar.
Alguém em algum lugar
@ SomeoneSomewhere Apenas salve o método Subscriptionretornado .subscribe()na variável e chame subscription.unsubscribe()quando quiser parar o cronômetro.
Micer
2

Ele é uma solução mais simples, funciona bem no meu aplicativo.

  public class MyActivity extends Acitivity {

    TextView myTextView;
    boolean someCondition=true;

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_activity);

            myTextView = (TextView) findViewById(R.id.refreshing_field);

            //starting our task which update textview every 1000 ms
            new RefreshTask().execute();



        }

    //class which updates our textview every second

    class RefreshTask extends AsyncTask {

            @Override
            protected void onProgressUpdate(Object... values) {
                super.onProgressUpdate(values);
                String text = String.valueOf(System.currentTimeMillis());
                myTextView.setText(text);

            }

            @Override
            protected Object doInBackground(Object... params) {
                while(someCondition) {
                    try {
                        //sleep for 1s in background...
                        Thread.sleep(1000);
                        //and update textview in ui thread
                        publishProgress();
                    } catch (InterruptedException e) {
                        e.printStackTrace(); 

                };
                return null;
            }
        }
    }
Rodion Altshuler
fonte
2

Você deseja que suas atualizações de interface do usuário ocorram no encadeamento de interface de usuário já existente.

A melhor maneira é usar um manipulador que use postDelayed para executar um Runnable após um atraso (cada execução agendará a próxima); limpe o retorno de chamada com removeCallbacks.

Você já está procurando o lugar certo, então olhe novamente, talvez esclareça por que esse exemplo de código não é o que você deseja. (Consulte também o artigo idêntico em Atualizando a interface do usuário a partir de um timer ).

Liudvikas Bukys
fonte
Infelizmente, seu link está morto. Não consigo encontrar rapidamente o artigo correto de volta.
Lekensteyn
Link de
Risinek
1

Aqui está uma maneira simples e confiável ...

Coloque o seguinte código em sua Atividade, e o método tick () será chamado a cada segundo no thread da interface do usuário enquanto sua atividade estiver no estado "resumido". Obviamente, você pode alterar o método tick () para fazer o que quiser ou para ser chamado com mais ou menos frequência.

@Override
public void onPause() {
    _handler = null;
    super.onPause();
}

private Handler _handler;

@Override
public void onResume() {
    super.onResume();
    _handler = new Handler();
    Runnable r = new Runnable() {
        public void run() {
            if (_handler == _h0) {
                tick();
                _handler.postDelayed(this, 1000);
            }
        }

        private final Handler _h0 = _handler;
    };
    r.run();
}

private void tick() {
    System.out.println("Tick " + System.currentTimeMillis());
}

Para os interessados, o código "_h0 = _handler" é necessário para evitar a execução simultânea de dois cronômetros, se sua atividade for pausada e retomada dentro do período de tick.

Adam Gawne-Cain
fonte
2
Por que fazer isso estranho _h0abordagem, em vez de removeCallbacksnos onPause, como toda a gente?
Página
1

Você também pode usar um animador para isso:

int secondsToRun = 999;

ValueAnimator timer = ValueAnimator.ofInt(secondsToRun);
timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator());
timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
    {
        @Override
        public void onAnimationUpdate(ValueAnimator animation)
        {
            int elapsedSeconds = (int) animation.getAnimatedValue();
            int minutes = elapsedSeconds / 60;
            int seconds = elapsedSeconds % 60;

            textView.setText(String.format("%d:%02d", minutes, seconds));
        }
    });
timer.start();
TpoM6oH
fonte
0

Você precisa criar um thread para lidar com o loop de atualização e usá-lo para atualizar a área de texto. A parte complicada, porém, é que apenas o thread principal pode realmente modificar a interface do usuário, portanto o thread do loop de atualização precisa sinalizar o thread principal para fazer a atualização. Isso é feito usando um manipulador.

Confira este link: http://developer.android.com/guide/topics/ui/dialogs.html# Clique na seção "Exemplo de ProgressDialog de exemplo com um segundo thread". É um exemplo exatamente do que você precisa fazer, exceto com uma caixa de diálogo de progresso em vez de um campo de texto.

usuario
fonte
Não faça isso. Existe uma classe simples de timer que faz tudo isso para você. E essa pergunta não tem nada a ver com diálogos de progresso ou diálogos.
Falmarri
Você olhou para a seção do link que eu publiquei ou você acabou de ver a palavra diálogo e assumir? O código é 100% relevante. Além disso, para sua informação, se você usar o timer, ainda estará criando um thread para lidar com o loop de atualização. Você ainda precisará usar o manipulador conforme descrito no link que eu publiquei.
Nick
Infelizmente, a página vinculada não contém mais uma seção com o título mencionado. Ao vincular ao código, deve-se sempre incluir o trecho de chave diretamente na sua resposta.
Página
0
void method(boolean u,int max)
{
    uu=u;
    maxi=max;
    if (uu==true)
    { 
        CountDownTimer uy = new CountDownTimer(maxi, 1000) 
  {
            public void onFinish()
            {
                text.setText("Finish"); 
            }

            @Override
            public void onTick(long l) {
                String currentTimeString=DateFormat.getTimeInstance().format(new Date());
                text.setText(currentTimeString);
            }
        }.start();
    }

    else{text.setText("Stop ");
}
kamilia jaber
fonte
2
Talvez alguma indentação de código e explicações de código sejam úteis.
Raul Rene
0

Se alguém estiver interessado, comecei a brincar com a criação de um objeto padrão para executar em um segmento da interface do usuário de atividades. Parece funcionar bem. Comentários bem-vindos. Eu adoraria que isso estivesse disponível no designer de layout como um componente para arrastar para uma atividade. Não posso acreditar que algo assim ainda não exista.

package com.example.util.timer;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;

public class ActivityTimer {

    private Activity m_Activity;
    private boolean m_Enabled;
    private Timer m_Timer;
    private long m_Delay;
    private long m_Period;
    private ActivityTimerListener m_Listener;
    private ActivityTimer _self;
    private boolean m_FireOnce;

    public ActivityTimer() {
        m_Delay = 0;
        m_Period = 100;
        m_Listener = null;
        m_FireOnce = false;
        _self = this;
    }

    public boolean isEnabled() {
        return m_Enabled;
    }

    public void setEnabled(boolean enabled) {
        if (m_Enabled == enabled)
            return;

        // Disable any existing timer before we enable a new one
        Disable();

        if (enabled) {
            Enable();
        }
    }

    private void Enable() {
        if (m_Enabled)
            return;

        m_Enabled = true;

        m_Timer = new Timer();
        if (m_FireOnce) {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay);
        } else {
            m_Timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    OnTick();
                }
            }, m_Delay, m_Period);
        }
    }

    private void Disable() {
        if (!m_Enabled)
            return;

        m_Enabled = false;

        if (m_Timer == null)
            return;

        m_Timer.cancel();
        m_Timer.purge();
        m_Timer = null;
    }

    private void OnTick() {
        if (m_Activity != null && m_Listener != null) {
            m_Activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    m_Listener.OnTimerTick(m_Activity, _self);
                }
            });
        }
        if (m_FireOnce)
            Disable();
    }

    public long getDelay() {
        return m_Delay;
    }

    public void setDelay(long delay) {
        m_Delay = delay;
    }

    public long getPeriod() {
        return m_Period;
    }

    public void setPeriod(long period) {
        if (m_Period == period)
            return;
        m_Period = period;
    }

    public Activity getActivity() {
        return m_Activity;
    }

    public void setActivity(Activity activity) {
        if (m_Activity == activity)
            return;
        m_Activity = activity;
    }

    public ActivityTimerListener getActionListener() {
        return m_Listener;
    }

    public void setActionListener(ActivityTimerListener listener) {
        m_Listener = listener;
    }

    public void start() {
        if (m_Enabled)
            return;
        Enable();
    }

    public boolean isFireOnlyOnce() {
        return m_FireOnce;
    }

    public void setFireOnlyOnce(boolean fireOnce) {
        m_FireOnce = fireOnce;
    }
}

Na atividade, tenho este onStart:

@Override
protected void onStart() {
    super.onStart();

    m_Timer = new ActivityTimer();
    m_Timer.setFireOnlyOnce(true);
    m_Timer.setActivity(this);
    m_Timer.setActionListener(this);
    m_Timer.setDelay(3000);
    m_Timer.start();
}
James Barwick
fonte
1
cara, o que há de errado com o ActivityTimerListener? Meu pacote ADT disse que não existe essa classe.
21813 Sorokin Andrey #
0
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 CheckBox optSingleShot;
 Button btnStart, btnCancel;
 TextView textCounter;

 Timer timer;
 MyTimerTask myTimerTask;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  optSingleShot = (CheckBox)findViewById(R.id.singleshot);
  btnStart = (Button)findViewById(R.id.start);
  btnCancel = (Button)findViewById(R.id.cancel);
  textCounter = (TextView)findViewById(R.id.counter);

  btnStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {

    if(timer != null){
     timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
     //singleshot delay 1000 ms
     timer.schedule(myTimerTask, 1000);
    }else{
     //delay 1000ms, repeat in 5000ms
     timer.schedule(myTimerTask, 1000, 5000);
    }
   }});

  btnCancel.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    if (timer!=null){
     timer.cancel();
     timer = null;
    }
   }
  });

 }

 class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat simpleDateFormat = 
     new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
   final String strDate = simpleDateFormat.format(calendar.getTime());

   runOnUiThread(new Runnable(){

    @Override
    public void run() {
     textCounter.setText(strDate);
    }});
  }

 }

}

.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:autoLink="web"
    android:text="http://android-er.blogspot.com/"
    android:textStyle="bold" />
<CheckBox 
    android:id="@+id/singleshot"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Single Shot"/>

Zar E Ahmer
fonte
Vejo que você adicionou isso vários anos após a pergunta e as respostas originais. Por favor, adicione uma explicação de como esta resposta se compara a outras respostas que já estavam lá. Por que você adicionou outro - que benefício / quando útil / que deficiência você viu em outras respostas?
Página
Eu apenas compartilho um código que está fazendo o mesmo trabalho com uma abordagem diferente. Mas sempre que você quiser atualizar os dados de qualquer visualização. Você deve usar o manipulador para isso. porque muitas vezes tenho notado que o uso de um timertask para atualizar uma exibição não funciona. O método @ Dave.B é mais correto para o meu conhecimento.
Zar E Ahmer
0

Se você já tem tempo delta.

public class Timer {
    private float lastFrameChanged;
    private float frameDuration;
    private Runnable r;

    public Timer(float frameDuration, Runnable r) {
        this.frameDuration = frameDuration;
        this.lastFrameChanged = 0;
        this.r = r;
    }

    public void update(float dt) {
        lastFrameChanged += dt;

        if (lastFrameChanged > frameDuration) {
            lastFrameChanged = 0;
            r.run();
        }
    }
}
Matthew Hooker
fonte
0

Afastei o Timer e fiz dele uma aula separada:

Timer.java

import android.os.Handler;

public class Timer {

    IAction action;
    Handler timerHandler = new Handler();
    int delayMS = 1000;

    public Timer(IAction action, int delayMS) {
        this.action = action;
        this.delayMS = delayMS;
    }

    public Timer(IAction action) {
        this(action, 1000);
    }

    public Timer() {
        this(null);
    }

    Runnable timerRunnable = new Runnable() {

        @Override
        public void run() {
            if (action != null)
                action.Task();
            timerHandler.postDelayed(this, delayMS);
        }
    };

    public void start() {
        timerHandler.postDelayed(timerRunnable, 0);
    }

    public void stop() {
        timerHandler.removeCallbacks(timerRunnable);
    }
}

E extrair a ação principal da Timerclasse como

IAction.java

public interface IAction {
    void Task();
}

E eu usei assim:

MainActivity.java

public class MainActivity extends Activity implements IAction{
...
Timer timerClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
        ...
        timerClass = new Timer(this,1000);
        timerClass.start();
        ...
}
...
int i = 1;
@Override
public void Task() {
    runOnUiThread(new Runnable() {

        @Override
        public void run() {
            timer.setText(i + "");
            i++;
        }
    });
}
...
}

Espero que isso ajude

Yashar Aliabbasi
fonte
0

Eu uso desta maneira:

String[] array={
       "man","for","think"
}; int j;

então abaixo do onCreate

TextView t = findViewById(R.id.textView);

    new CountDownTimer(5000,1000) {

        @Override
        public void onTick(long millisUntilFinished) {}

        @Override
        public void onFinish() {
            t.setText("I "+array[j] +" You");
            j++;
            if(j== array.length-1) j=0;
            start();
        }
    }.start();

é uma maneira fácil de resolver esse problema.

Mori
fonte
0

Para quem não pode confiar no cronômetro , criei uma classe de utilidade com uma das sugestões:

public class TimerTextHelper implements Runnable {
   private final Handler handler = new Handler();
   private final TextView textView;
   private volatile long startTime;
   private volatile long elapsedTime;

   public TimerTextHelper(TextView textView) {
       this.textView = textView;
   }

   @Override
   public void run() {
       long millis = System.currentTimeMillis() - startTime;
       int seconds = (int) (millis / 1000);
       int minutes = seconds / 60;
       seconds = seconds % 60;

       textView.setText(String.format("%d:%02d", minutes, seconds));

       if (elapsedTime == -1) {
           handler.postDelayed(this, 500);
       }
   }

   public void start() {
       this.startTime = System.currentTimeMillis();
       this.elapsedTime = -1;
       handler.post(this);
   }

   public void stop() {
       this.elapsedTime = System.currentTimeMillis() - startTime;
       handler.removeCallbacks(this);
   }

   public long getElapsedTime() {
       return elapsedTime;
   }
 }

para usar ... basta fazer:

 TimerTextHelper timerTextHelper = new TimerTextHelper(textView);
 timerTextHelper.start();

.....

 timerTextHelper.stop();
 long elapsedTime = timerTextHelper.getElapsedTime();
Alécio Carvalho
fonte