Eine Aufgabe zeitverzögert wiederholen?

Lesezeit: 10 Minuten

Eine Aufgabe zeitverzogert wiederholen
Kalpa Pathum Welivitigoda

Ich habe eine Variable in meinem Code, die besagt, dass es “Status” ist.

Ich möchte abhängig von diesem Variablenwert einen Text in der Anwendung anzeigen. Dies muss mit einer bestimmten Zeitverzögerung erfolgen.

Es ist wie,

  • Überprüfen Sie den Wert der Statusvariablen

  • Zeigen Sie etwas Text an

  • Warten Sie 10 Sekunden

  • Überprüfen Sie den Wert der Statusvariablen

  • Zeigen Sie etwas Text an

  • Warten Sie 15 Sekunden

und so weiter. Die Zeitverzögerung kann variieren und wird eingestellt, sobald der Text angezeigt wird.

Ich habe versucht Thread.sleep(time delay) und es ist fehlgeschlagen. Gibt es einen besseren Weg, dies zu erledigen?

  • Verwandte Frage: Wiederholen Sie eine Aufgabe mit einer Zeitverzögerung in einer benutzerdefinierten Ansicht

    – Suragch

    12. Juni 2017 um 11:10 Uhr

Eine Aufgabe zeitverzogert wiederholen
inazaruk

Du solltest benutzen Handler‘S postDelayed Funktion für diesen Zweck. Es führt Ihren Code mit einer bestimmten Verzögerung im Haupt-UI-Thread aus, sodass Sie die UI-Steuerelemente aktualisieren können.

private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;

@Override
protected void onCreate(Bundle bundle) {

    // your code here

    mHandler = new Handler();
    startRepeatingTask();
}

@Override
public void onDestroy() {
    super.onDestroy();
    stopRepeatingTask();
}

Runnable mStatusChecker = new Runnable() {
    @Override 
    public void run() {
          try {
               updateStatus(); //this function can change value of mInterval.
          } finally {
               // 100% guarantee that this always happens, even if
               // your update method throws an exception
               mHandler.postDelayed(mStatusChecker, mInterval);
          }
    }
};

void startRepeatingTask() {
    mStatusChecker.run(); 
}

void stopRepeatingTask() {
    mHandler.removeCallbacks(mStatusChecker);
}

  • Danke inazaruk, es geschafft, es zum Laufen zu bringen. Gefunden 2 v kleine Tippfehler (oben sein “Handler” nicht “Handle” und unten sein “removeCallbacks” nicht “removecallback” entfernen). Aber auf jeden Fall war der Code genau das, wonach ich gesucht habe. Ich versuche zu denken, was ich kann tun, um den Gefallen zu erwidern. Zumindest haben Sie meinen Respekt gewonnen. Mit freundlichen Grüßen Aubrey Bourke.

    – Aubreybourke

    16. Dezember 2011 um 12:13 Uhr

  • Schönes Programm, funktioniert einwandfrei. Aber die startRepeatingTask() musste aus der onCreate-Methode /UI-Thread aufgerufen werden (ich habe einige Zeit gebraucht, um das zu erkennen!), vielleicht hätte dieser Punkt irgendwo erwähnt werden können. Grüße

    – gkris

    21. August 2012 um 21:28 Uhr

  • Gibt es eine Möglichkeit, ein wiederholtes Runnable in der Methode getView() eines Adapters zu haben?

    – Etienne Lawlor

    22. Juli 2014 um 6:53 Uhr

  • Wenn wir hier Klassen importieren, was sollten wir importieren? android.os.Handler oder java.util.logging.Handler ?

    – EJ Chathuranga

    26. September 2017 um 9:29 Uhr


  • @inazruk, deine Lösung tut es nicht funktionieren, wenn Sie stopRepeatingTask() innerhalb des Runnable ausführen müssen, sagen wir, nachdem Sie den Wert der Variablen überprüft haben. Da Sie in einem finally-Block postDelayed sind.

    – wie Judo

    8. Januar 2018 um 16:41 Uhr


Eine Aufgabe zeitverzogert wiederholen
Ravemir

Für alle Interessierten, hier ist eine Klasse, die ich mit dem Code von inazaruk erstellt habe, der alles Notwendige erstellt (ich habe sie UIUpdater genannt, weil ich sie verwende, um die Benutzeroberfläche regelmäßig zu aktualisieren, aber Sie können sie beliebig nennen):

import android.os.Handler;
/**
 * A class used to perform periodical updates,
 * specified inside a runnable object. An update interval
 * may be specified (otherwise, the class will perform the 
 * update every 2 seconds).
 * 
 * @author Carlos Simões
 */
public class UIUpdater {
        // Create a Handler that uses the Main Looper to run in
        private Handler mHandler = new Handler(Looper.getMainLooper());

        private Runnable mStatusChecker;
        private int UPDATE_INTERVAL = 2000;

        /**
         * Creates an UIUpdater object, that can be used to
         * perform UIUpdates on a specified time interval.
         * 
         * @param uiUpdater A runnable containing the update routine.
         */
        public UIUpdater(final Runnable uiUpdater) {
            mStatusChecker = new Runnable() {
                @Override
                public void run() {
                    // Run the passed runnable
                    uiUpdater.run();
                    // Re-run it after the update interval
                    mHandler.postDelayed(this, UPDATE_INTERVAL);
                }
            };
        }

        /**
         * The same as the default constructor, but specifying the
         * intended update interval.
         * 
         * @param uiUpdater A runnable containing the update routine.
         * @param interval  The interval over which the routine
         *                  should run (milliseconds).
         */
        public UIUpdater(Runnable uiUpdater, int interval){
            UPDATE_INTERVAL = interval;
            this(uiUpdater);
        }

        /**
         * Starts the periodical update routine (mStatusChecker 
         * adds the callback to the handler).
         */
        public synchronized void startUpdates(){
            mStatusChecker.run();
        }

        /**
         * Stops the periodical update routine from running,
         * by removing the callback.
         */
        public synchronized void stopUpdates(){
            mHandler.removeCallbacks(mStatusChecker);
        }
}

Sie können dann ein UIUpdater-Objekt in Ihrer Klasse erstellen und es wie folgt verwenden:

...
mUIUpdater = new UIUpdater(new Runnable() {
         @Override 
         public void run() {
            // do stuff ...
         }
    });

// Start updates
mUIUpdater.startUpdates();

// Stop updates
mUIUpdater.stopUpdates();
...

Wenn Sie dies als Aktivitäts-Updater verwenden möchten, fügen Sie den Start-Aufruf in die onResume()-Methode und den Stopp-Aufruf in die onPause()-Methode ein, sodass die Aktualisierungen entsprechend der Aktivitätssichtbarkeit beginnen und stoppen.

  • Bearbeitet: UPDATE_INTERVAL = interval; sollte sein Vor this(uiUpdater); in UIUpdater(Runnable uiUpdater, int interval) (als Wert von UPDATE_INTERVAL verwendet und sollte als Parameter übergeben werden interval;). Vermeiden Sie auch eine Breite von über 80 Zeichen im Code, wenn möglich (fast immer 😉

    – Herr_und_Frau_D

    15. März 2013 um 9:24 Uhr


  • Diese Klasse hat eine Reihe von Problemen. An erster Stelle sollte es im Haupt-Thread instanziiert werden, um die GUI aktualisieren zu können. Sie hätten dies lösen können, indem Sie den Hauptlooper an den Handler-Konstruktor übergeben: new Handler(Looper.getMainLooper()). Zweitens validiert es keine Argumente, also schluckt es Null-Runnables und negative Intervalle. Schließlich wird die in der verbrachte Zeit nicht berücksichtigt uiUpdater.run() line und behandelt auch keine möglichen Ausnahmen, die von dieser Methode ausgelöst werden. Auch ist es nicht threadsicher, sollte man machen start und stop synchronisierte Methoden.

    – Herr Schmidt

    22. August 2013 um 7:39 Uhr

  • Bis zum Argumentvalidierungsteil bearbeitet, da ich Eclipse hier nicht habe, um den Code zu testen. Danke für die Rückmeldung! Meinten Sie das? StartUpdates und stopUpdates synchronisiert und einen Looper.getMainLooper()-Aufruf in den Handler-Konstruktor eingefügt (ich hoffe, Sie können ihn direkt aus der Felddeklaration aufrufen)

    – Ravemir

    22. August 2013 um 15:12 Uhr

  • Ich bekomme das: error: call to this must be first statement in constructor vielleicht gibt es eine einfache Lösung.

    – msysmilu

    23. April 2015 um 14:33 Uhr

  • Upvoting für Import – es braucht Zeit, um herauszufinden, woher Handler kommt, wenn man beiläufig in Java programmiert

    – Roman Susi

    28. Oktober 2015 um 18:37 Uhr

Ich denke, die neue Schärfe ist, a zu verwenden ScheduledThreadPoolExecutor. So:

private final ScheduledThreadPoolExecutor executor_ = 
        new ScheduledThreadPoolExecutor(1);
this.executor_.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
    update();
    }
}, 0L, kPeriod, kTimeUnit);

  • Executors.newSingleThreadScheduledExecutor() kann hier eine weitere Option sein.

    – Gulschan

    29. Oktober 2015 um 11:59 Uhr

1646638390 470 Eine Aufgabe zeitverzogert wiederholen
Hitesh Sahu

Es gibt 3 Möglichkeiten, dies zu tun:

Verwenden Sie ScheduledThreadPoolExecutor

Ein bisschen übertrieben, da Sie keinen Thread-Pool benötigen

   //----------------------SCHEDULER-------------------------
    private final ScheduledThreadPoolExecutor executor_ =
            new ScheduledThreadPoolExecutor(1);
     ScheduledFuture<?> schedulerFuture;
   public void  startScheduler() {
       schedulerFuture=  executor_.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                //DO YOUR THINGS
                pageIndexSwitcher.setVisibility(View.GONE);
            }
        }, 0L, 5*MILLI_SEC,  TimeUnit.MILLISECONDS);
    }


    public void  stopScheduler() {
        pageIndexSwitcher.setVisibility(View.VISIBLE);
        schedulerFuture.cancel(false);
        startScheduler();
    }

Verwenden Sie die Timer-Aufgabe

Alter Android-Stil

    //----------------------TIMER  TASK-------------------------

    private Timer carousalTimer;
    private void startTimer() {
        carousalTimer = new Timer(); // At this line a new Thread will be created
        carousalTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                //DO YOUR THINGS
                pageIndexSwitcher.setVisibility(INVISIBLE);
            }
        }, 0, 5 * MILLI_SEC); // delay
    }

    void stopTimer() {
        carousalTimer.cancel();
    }

Verwenden Sie Handler und Runnable

Moderner Android-Stil

    //----------------------HANDLER-------------------------

    private Handler taskHandler = new android.os.Handler();

    private Runnable repeatativeTaskRunnable = new Runnable() {
        public void run() {
            //DO YOUR THINGS
        }
    };

   void startHandler() {
        taskHandler.postDelayed(repeatativeTaskRunnable, 5 * MILLI_SEC);
    }

    void stopHandler() {
        taskHandler.removeCallbacks(repeatativeTaskRunnable);
    }

Non-Leaky Handler mit Aktivität/Kontext

Deklarieren Sie eine innere Handler-Klasse, die keinen Speicher in Ihrer Aktivitäts-/Fragmentklasse verliert

/**
     * Instances of static inner classes do not hold an implicit
     * reference to their outer class.
     */
    private static class NonLeakyHandler extends Handler {
        private final WeakReference<FlashActivity> mActivity;

        public NonLeakyHandler(FlashActivity activity) {
            mActivity = new WeakReference<FlashActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            FlashActivity activity = mActivity.get();
            if (activity != null) {
                // ...
            }
        }
    }

Deklarieren Sie ein Runnable, das Ihre sich wiederholende Aufgabe in Ihrer Activity/Fragment-Klasse ausführt

   private Runnable repeatativeTaskRunnable = new Runnable() {
        public void run() {
            new Handler(getMainLooper()).post(new Runnable() {
                @Override
                public void run() {

         //DO YOUR THINGS
        }
    };

Handler-Objekt in Ihrer Aktivität/Ihrem Fragment initialisieren (hier ist FlashActivity meine Aktivitätsklasse)

//Task Handler
private Handler taskHandler = new NonLeakyHandler(FlashActivity.this);

Wiederholen einer Aufgabe nach einem festen Zeitintervall

taskHandler.postDelayed (repeatativeTaskRunnable, DELAY_MILLIS);

Um die Wiederholung der Aufgabe zu stoppen

taskHandler .removeCallbacks(repeatativeTaskRunnable );

UPDATE: In Kotlin:

    //update interval for widget
    override val UPDATE_INTERVAL = 1000L

    //Handler to repeat update
    private val updateWidgetHandler = Handler()

    //runnable to update widget
    private var updateWidgetRunnable: Runnable = Runnable {
        run {
            //Update UI
            updateWidget()
            // Re-run it after the update interval
            updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
        }

    }

 // SATART updating in foreground
 override fun onResume() {
        super.onResume()
        updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
    }


    // REMOVE callback if app in background
    override fun onPause() {
        super.onPause()
        updateWidgetHandler.removeCallbacks(updateWidgetRunnable);
    }

1641943686 84 Sollte ich die Verwendung von Enums auf Android unbedingt vermeiden
Kai Wang

Timer funktioniert gut. Hier verwende ich Timer, um nach 1,5 Sekunden nach Text zu suchen und die Benutzeroberfläche zu aktualisieren. Ich hoffe, das hilft.

private Timer _timer = new Timer();

_timer.schedule(new TimerTask() {
    @Override
    public void run() {
        // use runOnUiThread(Runnable action)
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                search();
            }
        });
    }
}, timeInterval);

  • wo hast du die Intervallzeit eingetragen?

    – Nathiel Barros

    5. Juli 2017 um 8:56 Uhr

  • Hallo Nathiel, ich habe gerade meinen Beitrag aktualisiert, hoffe es hilft! Die Intervallzeit ist der zweite Parameter von Timer.schedule().

    – Kai Wang

    5. Juli 2017 um 18:03 Uhr

Mit kotlin und seiner Coroutine ist es ganz einfach, zuerst einen Job in Ihrer Klasse (besser in Ihrem viewModel) wie folgt zu deklarieren:

private var repeatableJob: Job? = null

dann, wenn Sie es erstellen und starten möchten, tun Sie dies:

repeatableJob = viewModelScope.launch {
    while (isActive) {
         delay(5_000)
         loadAlbums(iImageAPI, titleHeader, true)
    }
}
repeatableJob?.start()

und wenn du es beenden willst:

repeatableJob?.cancel()

PS: viewModelScope nur in Ansichtsmodellen verfügbar ist, können Sie andere Coroutine-Bereiche verwenden, z withContext(Dispatchers.IO)

Mehr Informationen: Hier

  • wo hast du die Intervallzeit eingetragen?

    – Nathiel Barros

    5. Juli 2017 um 8:56 Uhr

  • Hallo Nathiel, ich habe gerade meinen Beitrag aktualisiert, hoffe es hilft! Die Intervallzeit ist der zweite Parameter von Timer.schedule().

    – Kai Wang

    5. Juli 2017 um 18:03 Uhr

Der Timer ist eine weitere Möglichkeit, Ihre Arbeit zu erledigen, aber vergessen Sie nicht, ihn hinzuzufügen runOnUiThread wenn Sie mit UI arbeiten.

    import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

 CheckBox optSingleShot;
 Button btnStart, btnCancel;
 TextView textCounter;

 Timer timer;
 MyTimerTask myTimerTask;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  optSingleShot = (CheckBox)findViewById(R.id.singleshot);
  btnStart = (Button)findViewById(R.id.start);
  btnCancel = (Button)findViewById(R.id.cancel);
  textCounter = (TextView)findViewById(R.id.counter);

  btnStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {

    if(timer != null){
     timer.cancel();
    }

    //re-schedule timer here
    //otherwise, IllegalStateException of
    //"TimerTask is scheduled already" 
    //will be thrown
    timer = new Timer();
    myTimerTask = new MyTimerTask();

    if(optSingleShot.isChecked()){
     //singleshot delay 1000 ms
     timer.schedule(myTimerTask, 1000);
    }else{
     //delay 1000ms, repeat in 5000ms
     timer.schedule(myTimerTask, 1000, 5000);
    }
   }});

  btnCancel.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    if (timer!=null){
     timer.cancel();
     timer = null;
    }
   }
  });

 }

 class MyTimerTask extends TimerTask {

  @Override
  public void run() {
   Calendar calendar = Calendar.getInstance();
   SimpleDateFormat simpleDateFormat = 
     new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
   final String strDate = simpleDateFormat.format(calendar.getTime());

   runOnUiThread(new Runnable(){

    @Override
    public void run() {
     textCounter.setText(strDate);
    }});
  }

 }

}

und xml ist…

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:autoLink="web"
    android:text="http://android-er.blogspot.com/"
    android:textStyle="bold" />
<CheckBox 
    android:id="@+id/singleshot"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Single Shot"/>

Eine andere Möglichkeit, CountDownTimer zu verwenden

new CountDownTimer(30000, 1000) {

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

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();

Planen Sie einen Countdown bis zu einem Zeitpunkt in der Zukunft, mit regelmäßigen Benachrichtigungen zu Intervallen auf dem Weg. Beispiel für die Anzeige eines 30-Sekunden-Countdowns in einem Textfeld:

Für Details

  • Handler wird gegenüber Timer bevorzugt. Siehe Timer vs. Handler

    – Suragch

    12. Juni 2017 um 4:39 Uhr

964000cookie-checkEine Aufgabe zeitverzögert wiederholen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy