2012-04-18 9 views
28

Ho bisogno di eseguire del codice a intervalli regolari (collegarlo ad un server e prelevare dati dal database MySQL ogni minuto). A tal fine avere una classe di sincronizzazione:Android: eseguire il codice a intervalli regolari

public class Sync { 

    static private Handler handler = new Handler(); 
    Runnable task; 

    public Sync(Runnable task, long time) { 
     this.task = task; 
     handler.removeCallbacks(task); 
     handler.postDelayed(task, time); 
    } 
} 

e nella mia attività ho:

public void onCreate(Bundle savedInstanceState) { 
    ... 
    Sync sync = new Sync(call,60*1000); 
    ... 
} 

final private Runnable call = new Runnable() { 
    public void run() { 
    //This is where my sync code will be, but for testing purposes I only have a Log statement 
    Log.v("test","this will run every minute"); 
    } 
}; 

Ho provato questo con un periodo di tempo più breve per il test, ma funziona solo una volta. Quando registra il messaggio per la prima volta, è anche l'ultimo. Qualcuno vede cosa sto facendo qui? Grazie!

+0

scheduleWithFixedDelay da ScheduledThreadPoolExecutor è un'opzione più. –

risposta

48

È possibile farlo utilizzando il codice seguente, Spero che sia d'aiuto!

final Handler handler = new Handler(); 
Runnable runnable = new Runnable() { 

    @Override 
    public void run() { 
     try{ 
      //do your code here 
     } 
     catch (Exception e) { 
      // TODO: handle exception 
     } 
     finally{ 
      //also call the same runnable to call it at regular interval 
      handler.postDelayed(this, 1000); 
     } 
    } 
}; 
+2

Sì, questo è quello che stavo per dire. AlarmManager è più pesante e richiede la gestione di Intents per attivare il Runnable. Avere il tuo Runnable ri-pubblicare se stesso alla fine, se la strada da percorrere. E dovresti avvolgere il tuo codice nel Runnable con un try-finally e ripubblicare il Runnable nella sezione finally, per assicurarti che non venga mai saltato. – Greg

+1

Questo l'ha risolto, grazie! :) –

+27

Penso che il 'handler.postDelayed (this, 1000);' dovrebbe essere solo nella sezione finally (non alla fine del blocco try), altrimenti verrà postato due volte. – Parmaia

2

handler.postDelayed(task, time); eseguirà solo una volta, se si desidera che il codice per attivare a intervalli regolari, vorrei suggerire un Timer e un TimerTask invece di un Handler e Runnable.

TimerTasks può essere impostato per essere eseguito una volta, ogni x secondi o con un periodo fisso, ad es. x secondi - per quanto tempo ci sia voluto per l'ultima volta.

8

Per prima cosa è necessario dichiarare globalmente il gestore In secondo luogo, è necessario utilizzare nuovamente il metodo di post-delay in eseguibile per attivarlo nuovamente.

@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     Sync sync = new Sync(call,60*1000); 

    } 
    final private Runnable call = new Runnable() { 
     public void run() { 
     //This is where my sync code will be, but for testing purposes I only have a Log statement 
     Log.v("test","this will run every minute"); 
     handler.postDelayed(call,60*1000); 
     } 
    }; 
    public final Handler handler = new Handler(); 
    public class Sync { 


     Runnable task; 

     public Sync(Runnable task, long time) { 
      this.task = task; 
      handler.removeCallbacks(task); 
      handler.postDelayed(task, time); 
     } 
    } 


} 
1
 private void doSomethingRepeatedly() { 
     timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 

        try{ 

        //Your code 

        } 
        catch (Exception e) { 
         // TODO: handle exception 
        } 

      } 
      }, 0, 10000); 
        } 
0

Un modo alternativo, utilizzando di ScheduledExecutorService scheduleAtFixedRate:

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 

public void beepEvery10Seconds() { 
    final Runnable beeper = new Runnable() { 
     public void run() { System.out.println("beep"); } 
    }; 
    final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, 0, 10, SECONDS); 
} 
Problemi correlati