Come eseguire un metodo ogni X secondi


114

Sto sviluppando un'applicazione Android 2.3.3 e devo eseguire un metodo ogni X secondi .

In iOS, ho NSTimer , ma in Android non so cosa usare.

Qualcuno mi ha consigliato Handler ; un altro mi consiglia AlarmManager ma non so quale metodo si adatta meglio NSTimer .

Questo è il codice che voglio implementare in Android:

timer2 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/20.0f)
    target:self
    selector:@selector(loopTask)
    userInfo:nil
    repeats:YES
];

timer1 = [
    NSTimer scheduledTimerWithTimeInterval:(1.0f/4.0f)
    target:self
    selector:@selector(isFree)
    userInfo:nil
    repeats:YES
];

Ho bisogno di qualcosa che funzioni funzioni NSTimer .

Cosa mi consigliate?


1
Definisci "il migliore". In che modo vuoi che sia il migliore?
— Simon Forsberg

Non so quale metodo si adatta meglio a NSTimer.
— VansFannel

@VansFannel Quanto tempo vuoi per un intervallo?
— FoamyGuy

Ho aggiornato la domanda con i dettagli su ciò che sto cercando di fare.
— VansFannel

Questa domanda: stackoverflow.com/questions/6242268/… , è simile a questa e ha un'ottima risposta.
— VansFannel

Risposte:


168

Questo dipende davvero da quanto tempo occorre per eseguire la funzione.

Se è => 10 minuti → Vorrei andare con Alarm Manager.

// Some time when you want to run
Date when = new Date(System.currentTimeMillis());    

try{
   Intent someIntent = new Intent(someContext,MyReceiver.class); // intent to be launched

   // note this could be getActivity if you want to launch an activity
   PendingIntent pendingIntent = PendingIntent.getBroadcast(
        context, 
        0, // id, optional
        someIntent, // intent to launch
        PendingIntent.FLAG_CANCEL_CURRENT); // PendintIntent flag

   AlarmManager alarms = (AlarmManager) context.getSystemService(
        Context.ALARM_SERVICE);

   alarms.setRepeating(AlarmManager.RTC_WAKEUP,
        when.getTime(),
        AlarmManager.INTERVAL_FIFTEEN_MINUTES,
        pendingIntent); 

}catch(Exception e){
   e.printStackTrace();
}

E poi ricevi queste trasmissioni tramite il ricevitore di trasmissione. Si noti che questo dovrà essere registrato ether nel manifest dell'applicazione o tramite il context.registerReceiver(receiver,filter);metodo. Per ulteriori informazioni sui ricevitori di trasmissione, fare riferimento ai documenti ufficiali. Ricevitore di trasmissione .

public class MyReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
         //do stuffs
    }
}

Se è = <10 minuti → Vorrei andare con un gestore.

Handler handler = new Handler();
int delay = 1000; //milliseconds

handler.postDelayed(new Runnable(){
    public void run(){
        //do something
        handler.postDelayed(this, delay);
    }
}, delay);

3
Perché suggerimenti diversi a seconda del ritardo?
— Simon Forsberg

7
Efficienza, nella documentazione di AlarmManager si afferma che non dovrebbe essere utilizzato per attività ripetitive a piccoli intervalli.
— Jug6ernaut

9
@ SimonAndréForsberg nei documenti di AlarmManager afferma che Handler è il metodo preferito e più efficiente da utilizzare per i tick brevi: "Nota: Alarm Manager è inteso per i casi in cui si desidera che il codice dell'applicazione venga eseguito in un momento specifico, anche se l'applicazione non è attualmente in esecuzione. Per le normali operazioni di temporizzazione (tick, timeout, ecc.) è più facile e molto più efficiente utilizzare Handler. "
— FoamyGuy

Tuttavia, ho bisogno di eseguire un metodo nella stessa attività che ha avviato AlarmManager. Come lo posso fare?
— VansFannel

2
@ahmadalibaloch dall'interno del eseguibile che puoi fare h.removeCallbacks(this);, altrimenti devi mantenere un riferimento al eseguibile per poterlo rimuovere. Se si desidera il secondo, il metodo pubblicato qui potrebbe non essere il percorso migliore.
— Jug6ernaut


69

Puoi provare questo codice per chiamare il gestore ogni 15 secondi tramite onResume () e interromperlo quando l'attività non è visibile, tramite onPause ().

Handler handler = new Handler();
Runnable runnable;
int delay = 15*1000; //Delay for 15 seconds.  One second = 1000 milliseconds.


@Override
protected void onResume() {
   //start handler as activity become visible

    handler.postDelayed( runnable = new Runnable() {
        public void run() {
            //do something

            handler.postDelayed(runnable, delay);
        }
    }, delay);

    super.onResume();
}

// If onPause() is not included the threads will double up when you 
// reload the activity 

@Override
protected void onPause() {
    handler.removeCallbacks(runnable); //stop handler when activity not visible
    super.onPause();
}

5
Questo è quello che stavo cercando. Perfetto.
— viper

3
questa è la risposta perfetta!
— Riddhi

Spot on! L'utilizzo per il controllo della scheda selezionata corrente di MainActivitys in TabLayout corrisponde a questo frammento e, in caso contrario, interrompe il lavoro, poiché onPause () non riesce quando qualsiasi scheda selezionata di TabLayout su entrambi i lati di questa scheda selezionata
— BENN1TH

Perfetto. Questo era quello che stavo cercando :) 1 domanda, posso chiamare questo metodo da un'altra attività. O se ascolto questa attività questo oggetto verrà distrutto? Cosa succede se creo un gestore statico ed eseguibile. È possibile?
— hyperCoder

17

Se hai familiarità con RxJava, puoi usare Observable.interval (), che è abbastanza pulito.

Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(new Function<Long, ObservableSource<String>>() {
                @Override
                public ObservableSource<String> apply(@NonNull Long aLong) throws Exception {
                    return getDataObservable(); //Where you pull your data
                }
            });

Lo svantaggio di questo è che devi progettare il polling dei tuoi dati in un modo diverso. Tuttavia, ci sono molti vantaggi nel modo di programmazione reattiva:

  1. Invece di controllare i dati tramite una richiamata, crei un flusso di dati a cui ti iscrivi. Questo separa la preoccupazione della logica di "polling dei dati" e della logica di "compilazione dell'interfaccia utente con i dati" in modo da non mescolare il codice della "sorgente dati" e il codice dell'interfaccia utente.
  2. Con RxAndroid, puoi gestire i thread in sole 2 righe di codice.

    Observable.interval(60, TimeUnits.SECONDS)
          .flatMap(...) // polling data code
          .subscribeOn(Schedulers.newThread()) // poll data on a background thread
          .observeOn(AndroidSchedulers.mainThread()) // populate UI on main thread
          .subscribe(...); // your UI code

Si prega di controllare RxJava. Ha un'elevata curva di apprendimento ma renderà la gestione delle chiamate asincrone in Android molto più semplice e pulita.


4

Con Kotlin, ora possiamo creare una funzione generica per questo!

object RepeatHelper {
    fun repeatDelayed(delay: Long, todo: () -> Unit) {
        val handler = Handler()
        handler.postDelayed(object : Runnable {
            override fun run() {
                todo()
                handler.postDelayed(this, delay)
            }
        }, delay)
    }
}

E per usare, basta fare:

val delay = 1000L
RepeatHelper.repeatDelayed(delay) {
    myRepeatedFunction()
}

3
    new CountDownTimer(120000, 1000) {

        public void onTick(long millisUntilFinished) {
            txtcounter.setText(" " + millisUntilFinished / 1000);

        }

        public void onFinish() {

            txtcounter.setText(" TimeOut  ");
            Main2Activity.ShowPayment = false;
            EventBus.getDefault().post("go-main");

        }

    }.start();

4
Non inserire solo il codice di risposta. Si prega di modificare la tua risposta e aggiungere qualche spiegazione.
— Shashanth

2

Qui ho usato ripetutamente un thread in onCreate () un'attività, il timer non consente tutto in alcuni casi Thread è la soluzione

     Thread t = new Thread() {
        @Override
        public void run() {
            while (!isInterrupted()) {
                try {
                    Thread.sleep(10000);  //1000ms = 1 sec
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {

                            SharedPreferences mPrefs = getSharedPreferences("sam", MODE_PRIVATE);
                            Gson gson = new Gson();
                            String json = mPrefs.getString("chat_list", "");
                            GelenMesajlar model = gson.fromJson(json, GelenMesajlar.class);
                            String sam = "";

                            ChatAdapter adapter = new ChatAdapter(Chat.this, model.getData());
                            listview.setAdapter(adapter);
                           // listview.setStackFromBottom(true);
                          //  Util.showMessage(Chat.this,"Merhabalar");
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    t.start();

In caso fosse necessario, può essere fermato da

@Override
protected void onDestroy() {
    super.onDestroy();
    Thread.interrupted();
    //t.interrupted();
}

per favore descrivi la situazione in cui la mia risposta non funzionerà
— Umar Ata

Ciao Umar. Avevo bisogno di un cerchio per tutto il tempo in cui l'app è attiva, Handler ha reso viva la ripetizione mentre l'attività è viva, ma ho bisogno del cerchio mentre potevo visitare anche altre attività. Quindi il filo è la soluzione in questo modo sicuro che abbia anche la sua lotta.
— Sam

1

Qui potrebbe essere una risposta utile per il tuo problema utilizzando Rx Java e Rx Android .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.