2012-07-24 11 views
11

Po pierwsze, nie mogłem nawet wybrać metody użycia, czytam od wielu godzin, a ktoś mówi "Handlerów", ktoś mówi "Timer". Oto, co staram się osiągnąć:Android - Uruchom wątek powtarzalnie w obrębie timera

W preferencjach jest ustawienie (pole wyboru), które włącza/wyłącza powtarzanie pracy. Gdy to pole wyboru jest zaznaczone, timer powinien zacząć działać i wątek powinien być wykonywany co x sekund. Ponieważ pole wyboru nie jest zaznaczone, timer powinien się zatrzymać.

Oto mój kod:

Sprawdzenie czy jeśli pole jest zaznaczone, czy nie, jeśli sprawdzana void „refreshAllServers” zostanie wykonana który wykonuje pracę z zegarem.

boolean CheckboxPreference = prefs.getBoolean("checkboxPref", true); 
       if(CheckboxPreference == true) { 
        Main main = new Main(); 
        main.refreshAllServers("start"); 
       } else { 
        Main main = new Main(); 
        main.refreshAllServers("stop"); 
       } 

Pustka refreshAllServers że spełnia swoje zadanie czasomierza:

public void refreshAllServers(String start) { 

    if(start == "start") { 

     // Start the timer which will repeatingly execute the thread 

    } else { 

     // stop the timer 

      } 

A oto w jaki sposób wykonać mój wątek: (działa dobrze bez zegara)

Thread myThread = new MyThread(-5); 
       myThread.start(); 

Co próbowałem?

Próbowałem żadnego przykładu, który mogłem zobaczyć od Google (handlerki, timer), żaden z nich nie działał, udało mi się uruchomić timer raz, ale zatrzymanie go nie zadziałało. Najprostszy & zrozumiały kod widziałem w moich badań był następujący:

new java.util.Timer().schedule( 
     new java.util.TimerTask() { 
      @Override 
      public void run() { 
       // your code here 
      } 
     }, 
     5000 
); 
+1

Zobacz czy odpowiedź [tutaj] (http://stackoverflow.com/questions/8098806/where-do-i-create-and-use-scheduledthreadpoolexecutor-timertask-or-handler/8102488#8102488) pomaga. – yorkw

Odpowiedz

34

Wystarczy po prostu skorzystać z poniższego snippet

private Handler handler = new Handler(); 
private Runnable runnable = new Runnable() { 
    public void run() { 
     // 
     // Do the stuff 
     // 

     handler.postDelayed(this, 1000); 
    } 
}; 
runnable.run(); 

Aby przestać używać

handler.removeCallbacks(runnable); 

powinno załatwić sprawę.

+0

Twoje rozwiązanie również działa dobrze, ponieważ znalazłem inne rozwiązanie. – sarkolata

+0

Myślę, że to najlepsze rozwiązanie. –

+2

co, jeśli użytkownik chce wykonać coś, co korzysta z połączenia z Internetem? zastosowanie powyższego spowoduje, że program obsługi i działający będzie działał na wątku UI, co uniemożliwi wykonanie jakichkolwiek operacji sieciowych. Musisz tam zaimplementować wątek. – tony9099

1

Myślę używać AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html

Jeśli opcja nie jest zaznaczona na wywołanie metody gdzie

AlarmManager alarmManager = (AlarmManager)SecureDocApplication.getContext() 
    .getSystemService(Context.ALARM_SERVICE); 
PendingIntent myService = PendingIntent.getService(context, 0, 
       new Intent(context, MyService.class), 0); 

long triggerAtTime = 1000; 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 5000 /* 5 sec*/, 
       myService); 

Jeśli pole jest wyłączony anuluj menedżera alarmów

alarmManager.cancel(myService); 
+0

A która część wstawi mój kod? – sarkolata

+1

Mieć zmienną członka klasy, która jest instancją menedżera alarmów. Gdy pole wyboru jest włączone, wywołaj metodę z tym kodem. przy wyłączonej metodzie wywołania, aby zamknąć menedżera alarmów. To się stanie, gdy użytkownik przejrzy działania, a następnie odziedziczoną klasę aplikacji. Jeśli użytkownik może zamknąć aplikację i nadal musi być uruchomiony, a następnie korzystać z usługi. – Maxim

1

Użyj CountDownTimer. Sposób działania polega na wywołaniu metody na każdym haczyku licznika czasu i innej metodzie, gdy kończy się czas. W tym momencie można ponownie uruchomić w razie potrzeby. Sądzę, że prawdopodobnie powinieneś raczej wyrzucać AsyncTask zamiast wątków. Nie próbuj zarządzać własnymi wątkami w systemie Android. Spróbuj jak poniżej. Działa jak zegar.

CountDownTimer myCountdownTimer = new CountDownTimer(30000, 1000) { 

public void onTick(long millisUntilFinished) { 
    mTextField.setText("seconds remaining: " + millisUntilFinished/1000); 
    // Kick off your AsyncTask here. 
} 

public void onFinish() { 
    mTextField.setText("done!"); 
    // the 30 seconds is up now so do make any checks you need here. 
} 
}.start(); 
+0

To nie robi tego wielokrotnie. Raz się zatrzymał! – sarkolata

+0

Tak, nie działa bezterminowo. Jeśli chcesz uruchomić go w nieskończoność, możesz rozważyć usługę w tle. Z drugiej strony nic nie stoi na przeszkodzie, aby zrestartować timer odliczający czas, jeśli warunki są odpowiednie, lub od ustawienia dłuższego czasu. –

2

Dziękuję wszystkim, Naprawiłem ten problem przy użyciu Timera.

   timer = new Timer(); 
      timer.scheduleAtFixedRate( 
         new java.util.TimerTask() { 
          @Override 
          public void run() { 
           for(int i = 0; i < server_amount; i++) { 
             servers[i] = "Updating...";          handler.sendEmptyMessage(0); 
             new MyThread(i); 
             myThread.start(); 
         } 


        }}, 
        2000, 5000 
        ); 
+0

Proszę podać zalety tego rozwiązania w stosunku do innych. Nie widzę tego. –

+0

Bez zalet, właśnie dowiedziałem się, że odpowiedź Coders Paradise działa również po tym, jak pracowałem. – sarkolata

0

„[ScheduledThreadPoolExecutor] Klasa korzystnie czasowy, gdy potrzebnych jest wiele wątków roboczych lub gdy wymagana jest dodatkowa elastyczność lub możliwości ThreadPoolExecutor (który rozciąga się do tej klasy).”

za ...

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

To nie jest dużo więcej niż przewodnika, ale ma możliwość uruchomienia dokładnie tak często (wice opóźnienie po każdym zakończeniu obliczeń).

import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 


... 


final int THREAD_POOL_SIZE = 10; 
final int START_DELAY = 0; 
final int TIME_PERIOD = 5; 
final TimeUnit TIME_UNIT = TimeUnit.SECONDS; 

ScheduledThreadPoolExecutor pool; 

Runnable myPeriodicThread = new Runnable() { 
    @Override 
    public void run() { 
     refreshAllServers(); 
    } 
}; 


public void startTimer(){ 

    pool.scheduleAtFixedRate(myPeriodicThread, 
      START_DELAY, 
      TIME_PERIOD, 
      TIME_UNIT); 

} 

public void stopTimer(){ 

    pool.shutdownNow(); 

}