Como executar um tópico executável em Android em intervalos definidos?

desenvolvi uma aplicação para mostrar algum texto a intervalos definidos na tela do emulador Android. Estou a usar a classe Handler. Aqui está um trecho do meu código:

handler = new Handler();
Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");               
    }
};
handler.postDelayed(r, 1000);

Quando eu executar esta aplicação o texto é mostrado apenas uma vez. Por quê?

Author: Ravindra babu, 2009-12-17

10 answers

A solução simples para o seu exemplo é:

handler = new Handler();

final Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");
        handler.postDelayed(this, 1000);
    }
};

handler.postDelayed(r, 1000);

Ou podemos usar o tópico normal, por exemplo (com o corredor original) :

Thread thread = new Thread() {
    @Override
    public void run() {
        try {
            while(true) {
                sleep(1000);
                handler.post(this);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

thread.start();

Você pode considerar o seu objecto executável como um comando que pode ser enviado para a fila de mensagens para execução, e o handler como apenas um objecto auxiliar usado para enviar esse comando.

Mais detalhes estão aqui http://developer.android.com/reference/android/os/Handler.html

 470
Author: alex2k8, 2015-04-24 15:50:50

Eu acho que pode melhorar a primeira solução de Alex2k8 para atualizar correto a cada segundo

1.Código Original:

public void run() {
    tv.append("Hello World");
    handler.postDelayed(this, 1000);
}

2.Análise

  • no custo acima, assumir tv.append("Hello Word") o custo T milisegundos, após visualização 500 Os tempos de atraso são 500 * T milisegundos
  • irá aumentar com atraso quando durar muito tempo

3. Solução

Para evitar que apenas mude a ordem de postDelayed (), para evitar atrasado:

public void run() {
    handler.postDelayed(this, 1000);
    tv.append("Hello World");
}
 39
Author: NguyenDat, 2014-12-15 13:47:02
new Handler().postDelayed(new Runnable() {
    public void run() {
        // do something...              
    }
}, 100);
 32
Author: user2212515, 2017-06-23 19:25:38

Eu acredito que para este caso típico, isto é, para executar algo com um intervalo fixo, Timer é mais apropriado. Aqui está um exemplo simples:

myTimer = new Timer();
myTimer.schedule(new TimerTask() {          
@Override
public void run() {
    // If you want to modify a view in your Activity
    MyActivity.this.runOnUiThread(new Runnable()
        public void run(){
            tv.append("Hello World");
        });
    }
}, 1000, 1000); // initial delay 1 second, interval 1 second

Usar Timer tem poucas vantagens:

  • o atraso inicial e o intervalo podem ser facilmente especificados nos argumentos da função schedule
  • O temporizador pode ser parado simplesmente chamando myTimer.cancel()
  • Se quiser ter apenas um tópico a correr, lembre-se de ligar.myTimer.cancel() antes de marcar um novo (se o meu tempo for não nulo)
 23
Author: iTech, 2014-12-15 15:45:14

Para repetir a tarefa você pode usar

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);

Chama-lhe como

new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

            }
        },500,1000);

O código acima será executado pela primeira vez após meio segundo (500) e repetir-se-á após cada segundo(1000)

Onde

Tarefa sendo o método a ser executado

Após o tempo para a execução inicial

(intervalo {[9] } o tempo para repetir a execução)

Em Segundo Lugar

E você também pode usar CountDownTimer Se quiser executar uma tarefa várias vezes.

    new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

     public void onTick(long millisUntilFinished) {
      }
      public void onFinish() {
     }
    }.start();

//Above codes run 40 times after each second
E também podes fazê-lo com runnable. criar um método executável como
Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {

        }
    };

E chama-o de ambas as maneiras

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread

OU

new Thread(runnable).start();//to work in Background 
 22
Author: Xar E Ahmer, 2016-06-17 05:46:27
Handler handler=new Handler();
Runnable r = new Runnable(){
    public void run() {
        tv.append("Hello World");                       
        handler.postDelayed(r, 1000);
    }
}; 
handler.post(r);
 15
Author: singh arjun, 2014-06-21 18:25:16

Se bem entendi a documentação do Handler.Método post ():

Faz com que o R executável seja adicionado à fila de mensagens. O executável será executado no tópico ao qual este manipulador Está ligado.

Então os exemplos fornecidos por @alex2k8, embora estejam funcionando corretamente, não são os mesmos. No caso em que Handler.post() é usado, não são criados novos tópicos. Basta postar Runnable no tópico com Handler para ser executado por EDT . Depois disso, O EDT apenas executa Runnable.run(), nada mais.

Lembre-se.: Runnable != Thread.
 3
Author: Damian Walczak, 2012-10-08 21:44:59

Um exemplo interessante é que você pode ver continuamente um contador/relógio de parada rodando em um tópico separado. Também mostra a localização do GPS. Enquanto o tópico principal da Interface de usuário de atividade já está lá.

Excerto:

try {    
    cnt++; scnt++;
    now=System.currentTimeMillis();
    r=rand.nextInt(6); r++;    
    loc=lm.getLastKnownLocation(best);    

    if(loc!=null) { 
        lat=loc.getLatitude();
        lng=loc.getLongitude(); 
    }    

    Thread.sleep(100); 
    handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {   
    Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}

Para ver o código veja aqui:

Exemplo de tópico que mostra a localização do GPS e o tempo actual executável ao lado do tópico da Interface de Utilizador da actividade principal

 1
Author: Animesh Shrivastav, 2017-08-25 16:46:02

Agora no Kotlin você pode executar os tópicos desta forma:

class SimpleRunnable: Runnable {
    public override fun run() {
        println("${Thread.currentThread()} has run.")
    }
}
fun main(args: Array<String>) {
    val thread = SimpleThread()
    thread.start() // Will output: Thread[Thread-0,5,main] has run.
    val runnable = SimpleRunnable()
    val thread1 = Thread(runnable)
    thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
 0
Author: Andreh Abboud, 2018-07-25 18:25:11

Kotlin

private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
    val handler = Handler()
    runnable = Runnable {
        handler.postDelayed(runnable, 2000)
    }
    handler.postDelayed(runnable, 2000)
}

Java

Runnable runnable;
Handler handler;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            handler.postDelayed(this, 1000);
        }
    };
    handler.postDelayed(runnable, 1000);
}
 0
Author: Khemraj, 2018-09-21 13:29:45