917 Stimmen

Wie man eine Methode nach einer Verzögerung in Android aufruft

Ich möchte in der Lage sein, die folgende Methode nach einer bestimmten Verzögerung aufzurufen. In Objective C gab es etwas wie:

[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];

Gibt es ein Äquivalent zu dieser Methode in Android mit Java? Ich muss zum Beispiel in der Lage sein, eine Methode nach 5 Sekunden aufzurufen.

public void DoSomething()
{
     //do something here
}

7voto

Sam Punkte 5154

Hier gibt es also einiges zu beachten, denn es gibt so viele Möglichkeiten, diese Katze zu häuten. Obwohl alle Antworten bereits ausgewählt und ausgewählt worden sind. Ich denke, es ist wichtig, dass dies mit angemessenen Kodierungsrichtlinien überarbeitet wird, um zu vermeiden, dass irgendjemand in die falsche Richtung geht, nur weil die "Mehrheit eine einfache Antwort ausgewählt hat".

Lassen Sie uns also zunächst die einfache Antwort "Post Delayed" besprechen, die in diesem Thread als beste Antwort ausgewählt wurde.

Es gibt einige Dinge zu beachten. Nach der Post-Delay-Phase kann es zu Speicherlecks, toten Objekten, nicht mehr vorhandenen Lebenszyklen und vielem mehr kommen. Daher ist es wichtig, auch damit richtig umzugehen. Dazu gibt es mehrere Möglichkeiten.

Der modernen Entwicklung zuliebe werde ich in KOTLIN liefern

Hier ist ein einfaches Beispiel für die Verwendung des UI-Threads für einen Rückruf und die Bestätigung, dass Ihre Aktivität immer noch aktiv ist, wenn Sie Ihren Rückruf ausführen.

  Handler(Looper.getMainLooper()).postDelayed({
            if(activity != null && activity?.isFinishing == false){
                txtNewInfo.visibility = View.GONE
            }
        }, NEW_INFO_SHOW_TIMEOUT_MS)

Allerdings ist dies immer noch nicht perfekt, da es keinen Grund gibt, Ihre Callback zu treffen, wenn die Aktivität weg gegangen ist. so ein besserer Weg wäre, einen Verweis auf sie zu halten und entfernen Sie es Callbacks wie diese.

    private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
        A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
        if(activity != null && activity?.isFinishing == false){
            txtNewInfo.visibility = View.VISIBLE
            mHandler.postDelayed({
                if(activity != null && activity?.isFinishing == false){
                    txtNewInfo.visibility = View.GONE
                }
            }, NEW_INFO_SHOW_TIMEOUT_MS)
        }
    }

und natürlich Cleanup auf der onPause, so dass es nicht den Rückruf getroffen.

    override fun onPause() {
        super.onPause()
        mHandler.removeCallbacks(null)
    }

Nachdem wir nun das Offensichtliche besprochen haben, lassen Sie uns über eine sauberere Option mit modernen Coroutines und Kotlin sprechen :). Wenn Sie diese noch nicht verwenden, verpassen Sie wirklich etwas.

   fun doActionAfterDelay() 
        launch(UI) {
            delay(MS_TO_DELAY)           
            actionToTake()
        }
    }

oder wenn Sie immer einen UI-Start mit dieser Methode durchführen möchten, können Sie dies einfach tun:

  fun doActionAfterDelay() = launch(UI){ 
      delay(MS_TO_DELAY)           
      actionToTake()
  }

Natürlich müssen Sie genau wie bei PostDelayed sicherstellen, dass Sie das Abbrechen handhaben, so dass Sie entweder die Aktivitätsprüfungen nach dem Verzögerungsaufruf durchführen können oder es in der onPause genau wie die andere Route abbrechen können.

var mDelayedJob: Job? = null
fun doActionAfterDelay() 
   mDelayedJob = launch(UI) {
            try {
               delay(MS_TO_DELAY)           
               actionToTake()
            }catch(ex: JobCancellationException){
                showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
            }
        }
   }
}

//Griffbereinigung

override fun onPause() {
   super.onPause()
   if(mDelayedJob != null && mDelayedJob!!.isActive) {
      A35Log.v(mClassTag, "canceling delayed job")
      mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
   }
}

Wenn Sie launch(UI) in die Signatur der Methode aufnehmen, kann der Auftrag in der aufrufenden Codezeile zugewiesen werden.

Die Moral von der Geschichte ist also, dass Sie mit Ihren verzögerten Aktionen auf der sicheren Seite sein sollten. Stellen Sie sicher, dass Sie Ihre Rückrufe entfernen oder Ihre Aufträge abbrechen und natürlich sicherstellen, dass Sie den richtigen Lebenszyklus haben, um die Elemente auf Ihrem verzögerten Rückruf abzuschließen. Die Coroutines bietet auch abbrechbare Aktionen.

Es ist auch erwähnenswert, dass Sie normalerweise die verschiedenen Ausnahmen behandeln sollten, die mit Coroutines auftreten können. Zum Beispiel eine Annullierung, eine Ausnahme, eine Zeitüberschreitung, was auch immer Sie verwenden möchten. Hier ist ein fortgeschrittenes Beispiel, falls Sie sich entscheiden, Coroutines wirklich zu verwenden.

   mLoadJob = launch(UI){
            try {
                //Applies timeout
                withTimeout(4000) {
                    //Moves to background thread
                    withContext(DefaultDispatcher) {
                        mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
                    }
                }

                //Continues after async with context above
                showFancyToast("Loading complete", true, FancyToast.SUCCESS)
            }catch(ex: JobCancellationException){
                showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
            }catch (ex: TimeoutCancellationException) {
                showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
            }catch(ex: Exception){
                showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
            }
        }

6voto

Mr T Punkte 1238

Für eine einfache Zeile Handle Post delay, können Sie wie folgt vorgehen:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do someting
    }
}, 3000);

Ich hoffe, das hilft

5voto

Alnour Alharin Punkte 320

Durch die Verwendung der neu eingeführten Lambda-Ausdrücke können Sie dies wesentlich sauberer gestalten:

new Handler().postDelayed(() -> {/*your code here*/}, time);

5voto

Crime_Master_GoGo Punkte 1561

Sie können dies für Simplest Solution verwenden:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Write your code here
    }
}, 5000); //Timer is in ms here.

Andernfalls kann Below eine weitere saubere und nützliche Lösung sein:

new Handler().postDelayed(() -> 
{/*Do something here*/}, 
5000); //time in ms

4voto

Nikhil Katekhaye Punkte 1842

Mit Kotlin können wir Folgendes erreichen

Handler().postDelayed({
    // do something after 1000ms 
}, 1000)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X