Timertask sau Handler (Programare, Android, Performanță, Timer, Handler, Timertask)

keysersoze a intrebat.

Să spunem că vreau să efectuez o acțiune la fiecare 10 secunde și nu trebuie neapărat să actualizez vizualizarea.

Întrebarea este: este mai bine (adică mai eficient și mai eficace) să folosesc timerul cu timertask ca aici:

final Handler handler = new Handler();

TimerTask timertask = new TimerTask() {
    @Override
    public void run() {
        handler.post(new Runnable() {
            public void run() {
               <some task>
            }
        });
    }
};
timer = new Timer();
timer.schedule(timertask, 0, 15000);
}

sau doar un handler cu postdelayed

final Handler handler = new Handler(); 
final Runnable r = new Runnable()
{
    public void run() 
    {
        <some task>
    }
};
handler.postDelayed(r, 15000);

De asemenea, v-aș fi recunoscător dacă ați putea explica când să folosiți care abordare și de ce una dintre ele este mai eficientă decât alta (dacă este de fapt).

Comentarii

  • Am citit multe mesaje despre comportamentul neregulat al TimerTasks. Sfatul meu ar fi să mă feresc de ele și să folosesc abordarea handler / postDelayed. –  > Por Concepție sănătoasă.
  • Aș prefera metoda Handler-postDelay – ai mai mult control și o programezi din interior –  > Por mihail.
  • Iată o sursă excelentă pentru Timer vs. Handler –  > Por CodyF.
  • TimerTask este o sarcină de fundal, deci nu puteți actualiza UI. Spuneam și eu așa… –  > Por Yousha Aleayoub.
  • a funcționat pentru mine..mulțumesc –  > Por jyotsna.
3 răspunsuri
Suragch

Handler este mai bun decât TimerTask.

Java TimerTask și Android Handler ambele vă permit să programați sarcini întârziate și repetate pe fire de execuție în fundal. Cu toate acestea, literatura de specialitate recomandă în mod covârșitor utilizarea Handler în loc de TimerTask în Android (a se vedea aici, , aici, , aici, , aici, , aici, , și aici).

Unele dintre problemele raportate cu TimerTask includ:

  • Nu se poate actualiza firul UI
  • Scurgeri de memorie
  • Nesigură (nu funcționează întotdeauna)
  • Sarcinile care rulează mult timp pot interfera cu următorul eveniment programat

Exemplu

Cea mai bună sursă pentru toate tipurile de exemple Android pe care le-am văzut este la adresa Codepath. Iată un exemplu Handler exemplu de acolo pentru o sarcină care se repetă.

// Create the Handler object (on the main thread by default)
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableCode = new Runnable() {
    @Override
    public void run() {
      // Do something here on the main thread
      Log.d("Handlers", "Called on main thread");
      // Repeat this the same runnable code block again another 2 seconds
      handler.postDelayed(runnableCode, 2000);
    }
};
// Start the initial runnable task by posting through the handler
handler.post(runnableCode);

În legătură cu

Comentarii

  • @Reek Nu, GC ar trebui să se ocupe de asta. Dar trebuie să aveți grijă de runnable-ul postat pentru executarea întârziată. În exemplul de mai sus, runnable-ul utilizat este o instanță de clasă interioară, deci deține o referință implicită la clasa care o conține (care ar putea fi o activitate). Runnable-ul va rămâne în coada de mesaje a operatorului asociat cu looper-ul până la următorul moment de execuție, ceea ce poate fi după ce contextul este invalid și ar putea să se scurgă instanța clasei care îl conține. Puteți șterge astfel de referințe utilizând mHandler.removeCallbacks(runnableCode) la momentul potrivit (de exemplu onStop() pentru o activitate). –  > Por bitbybit.
  • Cel mai bun mod de prezentare a referințelor vreodată!!! (vezi aici, aici, aici, aici, aici, aici și aici). –  > Por Dunes Buggy.
  • și dacă vreau să folosesc asta în interiorul unui ViewModel? nu este împotriva idealului de a nu avea lucruri android acolo? –  > Por desgraci.
  • @desgraci, eu nu am folosit un ViewModel, dar din documentația văd doar că se spune că ViewModel nu ar trebui să acceseze ierarhia de vizualizare sau să conțină o referință la Activity sau Fragment. Nu văd nimic care să interzică să ai „lucruri Android” în general. –  > Por Suragch.
  • Începând de astăzi, aceste referințe sunt pentru mine depășite și nu sunt suficient de informative pentru a fi luate în considerare. Aceste 4 dezavantaje enumerate sunt reale doar dacă îți programezi prost codul. TimerTasks sunt în continuare o alegere foarte bună dacă doriți să executați periodic ceva în fundal și eventual să executați ceva pe UIThread dacă se aplică anumite condiții. –  > Por David.
Praveena

Există câteva dezavantaje ale utilizării Timer

Creează un singur fir de execuție pentru a executa sarcinile și, dacă o sarcină durează prea mult, celelalte sarcini au de suferit. Nu gestionează excepțiile aruncate de sarcini, iar firul de execuție se termină pur și simplu, ceea ce afectează alte sarcini programate și acestea nu sunt niciodată executate

Copiat din:

TimerTask vs Thread.sleep vs Handler postDelayed – cel mai corect este să apelați funcția la fiecare N milisecunde?

Comentarii

  • Deci, cum rămâne cu o sarcină de o singură dată? Sună ca și cum poate Timer este mai bun pentru asta, deoarece nu aveți cheltuielile generale ale cozii de mesaje? –  > Por Michael.
  • Cred că nu vom ști niciodată –  > Por Denny.
sma6871

Versiunea Kotlin a răspunsului acceptat:

// execute on the main thread, empty constructor is deprecated
val handler = Handler(Looper.getMainLooper())

val runnableCode = object : Runnable {
    override fun run() {
        Log.d("Handlers", "Called on main thread")
        handler.postDelayed(this, 2000)
    }
}

// or shorter using a lambda function
val runnableCode = Runnable {
    Log.d("Handlers", "Called on main thread")
    handler.postDelayed(this, 2000)
}

handler.post(runnableCode)

Comentarii

  • Ar fi util să adăugați un exemplu de Handler care rulează pe un fir separat, pentru sarcinile care nu trebuie să actualizeze ui. –  > Por JCarlosR.