Qual é o equivalente a um JavaScript setInterval / setTimeout no Android / Java?

129

Alguém pode me dizer se existe um equivalente para setInterval / setTimeout para o Android? Alguém tem algum exemplo de como fazer isso?

karse23
fonte

Respostas:

245

Como sempre no Android, há várias maneiras de fazer isso, mas supondo que você queira executar um pedaço de código um pouco mais tarde no mesmo thread, eu uso o seguinte:

new android.os.Handler().postDelayed(
    new Runnable() {
        public void run() {
            Log.i("tag", "This'll run 300 milliseconds later");
        }
    }, 
300);

.. isso é praticamente equivalente a

setTimeout( 
    function() {
        console.log("This will run 300 milliseconds later");
    },
300);
Ben Clayton
fonte
Esta é uma solução muito boa para a seleção gaveta e fragmentTransaction
Gonçalo
6
Como posso cancelá-lo se precisar?
Quentin Roy
Como você obtém o escopo da atividade no método run ()?
Andy
@Andy assim:MyActivityName.this.myFunctionOnActivity()
Ben Clayton
1
@QuentinRoy: Handler timeout = new Handler(); final Runnable r = new Runnable{...}; timeout.postDelayed(r, 300);e se você quiser cancelá-lo:timeout.removeCallbacks(r);
Bastian Springer
101

setInterval ()

função que se repete a cada n milissegundos

Javascript

 setInterval(function(){ Console.log("A Kiss every 5 seconds"); }, 5000);

Java aproximado equivalente

new Timer().scheduleAtFixedRate(new TimerTask(){
    @Override
    public void run(){
       Log.i("tag", "A Kiss every 5 seconds");
    }
},0,5000);

setTimeout ()

função que funciona somente após n milissegundos

Javascript

setTimeout(function(){ Console.log("A Kiss after 5 seconds"); },5000);

Java aproximado equivalente

new android.os.Handler().postDelayed(
    new Runnable() {
        public void run() {
            Log.i("tag","A Kiss after 5 seconds");
        }
}, 5000);
Midhun
fonte
5
Para o scheduleAtFixedRatemétodo, como você cancela o cronômetro dentro da atividade após o término dessa atividade?
auroranil
2
@ user824294, você pode salvar sua instância do Timer em uma variável e chamar "cancel ()" quando quiser interromper as tarefas agendadas - Timer t = new Timer (); t.scheduleAtFixedRate (...); - E então chame t.cancel (); sempre que desejar.
Aebsubis
14

Se você não está preocupado em ativar o telefone ou trazer seu aplicativo de volta dos mortos, tente:

// Param is optional, to run task on UI thread.     
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // Do the task...
        handler.postDelayed(this, milliseconds) // Optional, to repeat the task.
    }
};
handler.postDelayed(runnable, milliseconds);

// Stop a repeating task like this.
handler.removeCallbacks(runnable);
SharkAlley
fonte
No meu telefone (Huawei P Smart), o manipulador não acorda o dispositivo do modo de suspensão ( conforme comentado por apanloco em outra resposta )
Franco
13

Dependendo do que você realmente deseja alcançar, dê uma olhada nos Manipuladores do Android:

http://developer.android.com/reference/android/os/Handler.html

Se você já usou o javascript setTimeout () etc para agendar uma tarefa para execução no futuro, esta é a maneira do Android de fazer isso (postDelayed / sendMessageDelayed).

Observe que nem Handlers nem Timers fazem com que um telefone Android seja ativado no modo de suspensão. Em outras palavras, se você deseja agendar algo para realmente acontecer, mesmo que a tela esteja desligada / a CPU esteja inativa, você também deve verificar o AlarmManager.

apanloco
fonte
5

Não sei muito sobre JavaScript, mas acho que os Timers podem ser o que você está procurando.

http://developer.android.com/reference/java/util/Timer.html

No link:

O one-shot está programado para ser executado em um tempo absoluto ou após um atraso relativo. Tarefas recorrentes são agendadas com um período fixo ou uma taxa fixa.

nicholas.hauschild
fonte
Nota: Chama você em um encadeamento em segundo plano, não no encadeamento principal / UI.
Pang
Esta não é uma resposta, mas uma referência a informações externas que podem ou não conter a solução de OPs. Por favor, cole o código relevante que o OP pode usar!
Lev
5

A primeira resposta é definitivamente a resposta correta e é disso que eu baseei esta versão lambda, que é muito mais curta na sintaxe. Como Runnable possui apenas 1 método de substituição "run ()", podemos usar um lambda:

this.m_someBoolFlag = false;
new android.os.Handler().postDelayed(() -> this.m_someBoolFlag = true, 300);
neoRiley
fonte
5
import java.util.Timer;
import java.util.TimerTask;

class Clock {
    private Timer mTimer = new Timer();

    private int mSecondsPassed = 0;
    private TimerTask mTask = new TimerTask() {
        @Override
        public void run() {
            mSecondsPassed++;
            System.out.println("Seconds passed: " + mSecondsPassed);
        }
    };

    private void start() {
        mTimer.scheduleAtFixedRate(mTask, 1000, 1000);
    }

    public static void main(String[] args) {
        Clock c = new Clock();
        c.start();
    }
}
Jeeva
fonte
4

Aqui está um equivalente de setTimeout, útil principalmente ao tentar atualizar a interface do usuário após um atraso.

Como você deve saber, a atualização da interface do usuário pode ser feita apenas a partir do encadeamento da interface do usuário. O AsyncTask faz isso por você chamando seu método onPostExecute a partir desse segmento.

new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            // Update the User Interface
        }

    }.execute();
Stephane JAIS
fonte
3
1. Da mesma forma, onProgressUpdate()também pode ser usado para simular setInterval(). 2. AsyncTask roda em um conjunto de encadeamentos (ou apenas um único encadeamento), então a. pode ter que esperar até que outro AsyncTasktermine; b . ocupará um segmento da piscina.
Pang
Existem muitos problemas ao usar a tarefa assíncrona neste contexto (apenas um thread e o bloqueio de um thread sem motivo) - as outras soluções são muito melhores.
Elementar
4

Eu estava criando um mp3 player para android, queria atualizar o horário atual a cada 500ms, então fiz assim

setInterval

private void update() {
    new android.os.Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            long cur = player.getCurrentPosition();
            long dur = player.getDuration();
            currentTime = millisecondsToTime(cur);
            currentTimeView.setText(currentTime);
            if (cur < dur) {
                updatePlayer();
            }

            // update seekbar
            seekBar.setProgress( (int) Math.round((float)cur / (float)dur * 100f));
        }
    }, 500);
}

que chama o mesmo método recursivamente

ZeroErr0r
fonte