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?

VansFannel
quelle
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);
Jug6ernaut
quelle
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
101

Verwenden Sie den Timer für jede Sekunde ...

new Timer().scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        //your method
    }
}, 0, 1000);//put here time 1000 milliseconds=1 second
Samir Mangroliya
quelle
Ich habe die Frage mit Details zu dem, was ich versuche, aktualisiert.
VansFannel
4
Verwenden Sie keinen Timer ( mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler ), keinen Handler oder ScheduledThreadPoolExecutor.
AppiDevo
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();
}
Umar Ata
quelle
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.

wdina
quelle
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()
}
Luke
quelle
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();
Behzad F94
quelle
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();
}
Sam
quelle
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 .

Sepehr
quelle