So führen Sie alle X Sekunden eine Methode aus


114

Ich entwickle eine Android 2.3.3-Anwendung und muss alle X Sekunden eine Methode ausführen .

In iOS habe ich NSTimer , aber in Android weiß ich nicht, was ich verwenden soll.

Jemand hat mir Handler empfohlen ; Ein anderer empfiehlt mir AlarmManager, aber ich weiß nicht, welche Methode besser zu NSTimer passt .

Dies ist der Code, den ich in Android implementieren möchte:

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
];

Ich brauche etwas, das wie NSTimer funktioniert .

Was empfehlen Sie mir?


1
Definieren Sie "den besten". Inwiefern soll es das Beste sein?
Simon Forsberg

Ich weiß nicht, welche Methode besser zu NSTimer passt.
VansFannel

@VansFannel Wie lange von einem Intervall möchten Sie?
FoamyGuy

Ich habe die Frage mit Details zu dem, was ich versuche, aktualisiert.
VansFannel

Diese Frage: stackoverflow.com/questions/6242268/… ähnelt dieser und hat eine gute Antwort.
VansFannel

Antworten:


168

Dies hängt wirklich davon ab, wie lange Sie voneinander entfernt sein müssen, um die Funktion auszuführen.

Wenn es => 10 Minuten ist → würde ich mit Alarm Manager gehen.

// 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();
}

Und dann empfangen Sie diese Sendungen über den Rundfunkempfänger. Beachten Sie, dass dies in Ihrem Anwendungsmanifest oder über die context.registerReceiver(receiver,filter);Methode registriert werden muss. Weitere Informationen zu Rundfunkempfängern finden Sie in den offiziellen Dokumenten. Rundfunkempfänger .

public class MyReceiver extends BroadcastReceiver{

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

Wenn es = <10 Minuten → ist, würde ich mit einem Handler gehen.

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

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

3
Warum unterschiedliche Vorschläge je nach Zeitverzögerung?
Simon Forsberg

7
Effizienz In den AlarmManager-Dokumenten heißt es, dass es nicht für sich wiederholende Aufgaben mit kleinen Intervallen verwendet werden sollte.
Jug6ernaut

9
@ SimonAndréForsberg in den AlarmManager-Dokumenten besagt, dass Handler die bevorzugte und effizientere Methode für kurze Ticks ist: "Hinweis: Der Alarm Manager ist für Fälle vorgesehen, in denen Ihr Anwendungscode zu einem bestimmten Zeitpunkt ausgeführt werden soll, auch wenn Ihr Die Anwendung wird derzeit nicht ausgeführt. Für normale Timing-Vorgänge (Ticks, Timeouts usw.) ist die Verwendung von Handler einfacher und effizienter. "
FoamyGuy

Ich muss jedoch eine Methode in derselben Aktivität ausführen, in der der AlarmManager gestartet wurde. Wie kann ich das machen?
VansFannel

2
@ahmadalibaloch aus der ausführbaren Datei heraus, die Sie ausführen können h.removeCallbacks(this);, andernfalls müssen Sie einen Verweis auf die ausführbare Datei pflegen, um sie entfernen zu können. Wenn die zweite gewünscht wird, ist die hier angegebene Methode möglicherweise nicht die beste Route.
Jug6ernaut


69

Sie können diesen Code versuchen, um den Handler alle 15 Sekunden über onResume () aufzurufen und über onPause () zu stoppen, wenn die Aktivität nicht sichtbar ist.

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
Das habe ich gesucht. Perfekt.
Viper

3
das ist die perfekte Antwort!
Riddhi

Genau richtig! Mit für MainActivitys aktuell ausgewählte Registerkarte in TabLayout passt dieses Fragment und wenn nicht Stop Arbeit Überprüfung - wie onPause () schlägt fehl , wenn jede TabLayout Tabs beiden Seiten dieser ausgewählten Registerkarte ausgewählt
BENN1TH

perfekt. Dies war, wonach ich gesucht habe :) 1 Frage, kann ich diese Methode aus einer anderen Aktivität aufrufen. Oder wenn ich diese Aktivität belausche, wird dieses Objekt zerstört? Was ist, wenn ich einen statischen Handler erstelle und ausführbar bin? Ist das möglich?
HyperCoder

17

Wenn Sie mit RxJava vertraut sind, können Sie Observable.interval () verwenden, was ziemlich ordentlich ist.

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
                }
            });

Der Nachteil dabei ist, dass Sie Ihre Daten auf andere Weise abfragen müssen. Die reaktive Programmierung bietet jedoch viele Vorteile:

  1. Anstatt Ihre Daten über einen Rückruf zu steuern, erstellen Sie einen Datenstrom, den Sie abonnieren. Dies trennt das Problem der Logik "Daten abrufen" und der Logik "Benutzeroberfläche mit Ihren Daten füllen", sodass Sie Ihren "Datenquellen" -Code und Ihren Benutzeroberflächencode nicht mischen.
  2. Mit RxAndroid können Sie Threads in nur 2 Codezeilen verarbeiten.

    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

Bitte überprüfen Sie RxJava. Es hat eine hohe Lernkurve, aber es wird die Bearbeitung von asynchronen Anrufen in Android so viel einfacher und sauberer machen.


4

Mit Kotlin können wir jetzt eine generische Funktion dafür erstellen!

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

Und um es zu benutzen, machen Sie einfach:

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
Postleitzahl nicht nur beantworten. Bitte bearbeiten Sie Ihre Antwort und fügen Sie eine Erklärung hinzu.
Shashanth

2

Hier habe ich einen Thread in onCreate () wiederholt, eine Aktivität, Timer erlaubt nicht alles in einigen Fällen Thread ist die Lösung

     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();

Falls es benötigt wird, kann es von gestoppt werden

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

Bitte beschreiben Sie die Situation, in der meine Antwort nicht funktioniert
Umar Ata

Hallo Umar. Ich brauchte einen Kreis, während die App lebt. Handler hat die Wiederholung lebendig gemacht, während die Aktivität lebt, aber ich brauche den Kreis, während ich auch andere Aktivitäten besuchen konnte. Thread ist also eine Lösung auf diese Weise, die sicher auch ihren Kampf hat.
Sam

1

Hier vielleicht hilfreiche Antwort für Ihr Problem mit Rx Java & Rx Android .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.