it-swarm.com.de

So rufen Sie eine Methode nach einer Verzögerung in Android auf

Ich möchte die folgende Methode nach einer angegebenen Verzögerung aufrufen können . In Ziel C gab es so etwas wie:

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

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

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

Bessere Version - Kotlin:

Handler.postDelayed({
  //Do something after 100ms
}, 100);


Bessere Version - Java:

final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);


1599
kontinuity

Ich konnte keine der anderen Antworten in meinem Fall verwenden ... Ich verwendete stattdessen den nativen Java-Timer.

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // this code will be executed after 2 seconds       
    }
}, 2000);
281
Jules Colle

Hinweis: Diese Antwort wurde gegeben, wenn bei der Frage Android nicht als Kontext angegeben wurde. Für eine spezifische Antwort auf den Android UI-Thread siehe hier


Es sieht so aus, als würde die Mac OS-API den aktuellen Thread fortsetzen und die Task asynchron ausführen. In Java wird die entsprechende Funktion vom Java.util.concurrent-Paket bereitgestellt. Ich bin mir nicht sicher, welche Einschränkungen Android mit sich bringt.

private static final ScheduledExecutorService worker = 
  Executors.newSingleThreadScheduledExecutor();

void someMethod() {
  ⋮
  Runnable task = new Runnable() {
    public void run() {
      /* Do something… */
    }
  };
  worker.schedule(task, 5, TimeUnit.SECONDS);
  ⋮
}
180
erickson

Um nach 5 Sekunden etwas im UI-Thread auszuführen:

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something here
    }
}, 5000);
94
pomber

sie können Handler in UIThread verwenden:

runOnUiThread(new Runnable() {

    @Override
    public void run() {
         final Handler handler = new Handler();
         handler.postDelayed(new Runnable() {
           @Override
           public void run() {
               //add your code here
           }
         }, 1000);

    }
});
38
Hossam Ghareeb

Vielen Dank für all die tollen Antworten. Ich habe eine Lösung gefunden, die meinen Bedürfnissen am besten entspricht.

Handler myHandler = new DoSomething();
Message m = new Message();
m.obj = c;//passing a parameter here
myHandler.sendMessageDelayed(m, 1000);

class DoSomething extends Handler {
    @Override
    public void handleMessage(Message msg) {
      MyObject o = (MyObject) msg.obj;
      //do something here
    }
}
36
aryaxt

Diese Demo ansehen:

import Java.util.Timer;
import Java.util.TimerTask;

class Test {
     public static void main( String [] args ) {
          int delay = 5000;// in ms 

          Timer timer = new Timer();

          timer.schedule( new TimerTask(){
             public void run() { 
                 System.out.println("Wait, what..:");
              }
           }, delay);

           System.out.println("Would it run?");
     }
}
21
OscarRyz

Wenn Sie den Handler verwenden müssen, sich aber in einem anderen Thread befinden, können Sie runonuithread verwenden, um den Handler im UI-Thread auszuführen. Dies erspart Ihnen Ausnahmen, die nach Aufruf von Looper.Prepare() geworfen werden.

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //Do something after 1 second
            }
        }, 1000);
    }
});

Sieht ziemlich unordentlich aus, aber das ist einer der Wege.

21
noob

Ich bevorzuge die View.postDelayed()-Methode, den folgenden einfachen Code:

mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 1000 ms
    }
}, 1000);
16
codezjx

Hier ist meine kürzeste Lösung: 

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something after 100ms
    }
}, 100);
13
Alecs
final Handler handler = new Handler(); 
Timer t = new Timer(); 
t.schedule(new TimerTask() { 
    public void run() { 
        handler.post(new Runnable() { 
            public void run() { 
                //DO SOME ACTIONS HERE , THIS ACTIONS WILL WILL EXECUTE AFTER 5 SECONDS...
            }
        }); 
    } 
}, 5000); 
10
Vishnu

Wenn Sie Android Studio 3.0 oder höher verwenden, können Sie Lambda-Ausdrücke verwenden. Die Methode callMyMethod() wird nach 2 Sekunden aufgerufen:

new Handler().postDelayed(() -> callMyMethod(), 2000);

Falls Sie das verzögerte Runable abbrechen müssen, verwenden Sie das:

Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);

// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);
7
vovahost

Ich schlage vor, den Timer zu verwenden, damit Sie eine Methode festlegen können, die in einem bestimmten Intervall aufgerufen wird. Dadurch wird Ihre Benutzeroberfläche nicht blockiert und die App bleibt aktiv, während die Methode ausgeführt wird.

Die andere Option ist das wait (); method, dadurch wird der aktuelle Thread für die angegebene Zeitdauer blockiert. Dies führt dazu, dass Ihre Benutzeroberfläche nicht mehr reagiert, wenn Sie dies im UI-Thread tun.

6
Nate

Kotlin & Java Viele Möglichkeiten

1. Verwendung von Handler

Handler().postDelayed({
    TODO("Do something")
    }, 2000)

2. TimerTask verwenden

Timer().schedule(object : TimerTask() {
    override fun run() {
        TODO("Do something")
    }
}, 2000)

Oder noch kürzer

Timer().schedule(timerTask {
    TODO("Do something")
}, 2000)

Oder am kürzesten wäre

Timer().schedule(2000) {
    TODO("Do something")
}

3. Verwendung von Executors

Executors.newSingleThreadScheduledExecutor().schedule({
    TODO("Do something")
}, 2, TimeUnit.SECONDS)

In Java

1. Verwendung von Handler

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

2. Verwendung von Timer

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // Do something
    }
}, 2000);

3. Verwendung von ScheduledExecutorService

private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();

Runnable runnable = new Runnable() {
  public void run() {
      // Do something
  }
  };
worker.schedule(runnable, 2, TimeUnit.SECONDS);
5
Khemraj

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 unten eine andere saubere nützliche Lösung sein:

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

Sie können es viel sauberer machen, indem Sie die neu eingeführten Lambda-Ausdrücke verwenden:

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

Ich habe eine einfachere Methode entwickelt, um das aufzurufen. 

public static void CallWithDelay(long miliseconds, final Activity activity, final String methodName)
    {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                try {
                    Method method =  activity.getClass().getMethod(methodName);
                    method.invoke(activity);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }, miliseconds);
    }

Um es zu benutzen, rufen Sie einfach an: .CallWithDelay(5000, this, "DoSomething");

3
HelmiB

Es gibt also ein paar Dinge, die zu berücksichtigen sind, da es so viele Möglichkeiten gibt, diese Katze zu enthäuten. Obwohl alle Antworten bereits ausgewählt und ausgewählt wurden. Ich denke, es ist wichtig, dass dies mit den richtigen Kodierungsrichtlinien erneut durchdacht wird, um zu verhindern, dass jemand in die falsche Richtung geht, nur weil "die Mehrheit die Antwort gewählt hat".

Lassen Sie uns zuerst die einfache Antwort "Post Delayed" diskutieren, die in diesem Thread die gewählte Antwort darstellt.

Ein paar Dinge zu beachten. Nach der Nachverzögerung können Sie auf Gedächtnislecks, tote Objekte, abgelaufene Lebenszyklen und mehr stoßen. Der richtige Umgang damit ist ebenfalls wichtig. Sie können dies auf verschiedene Arten tun.

Für die moderne Entwicklung werde ich in KOTLIN liefern

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

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

Dies ist jedoch immer noch nicht perfekt, da es keinen Grund gibt, den Rückruf zu tätigen, wenn die Aktivität weg ist. Ein besserer Weg wäre es, einen Verweis darauf zu behalten und seine Callbacks so zu entfernen.

    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 mit der Bereinigung der onPause umgehen, damit der Callback nicht getroffen wird.

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

Nachdem wir das Offensichtliche besprochen haben, wollen wir mit den heutigen Coroutinen und Kotlin über eine sauberere Option sprechen :). Wenn Sie diese noch nicht verwenden, verpassen Sie das wirklich.

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

oder wenn Sie für diese Methode immer einen UI-Start durchführen möchten, können Sie einfach Folgendes tun:

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

Wie beim PostDelayed müssen Sie natürlich sicherstellen, dass Sie mit dem Abbruch fertig werden, sodass Sie entweder die Aktivitätsprüfungen nach dem Verzögerungsaufruf durchführen können oder Sie können ihn ebenso wie die andere Route in der onPause abbrechen.

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

// Bereinigung durchführen

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 den Start (UI) in die Methodensignatur einfügen, kann der Job in der aufrufenden Codezeile zugewiesen werden.

die Moral der Geschichte ist es also, mit Ihren verzögerten Aktionen sicher zu sein, sicherzustellen, dass Sie Ihre Rückrufe entfernen oder Ihre Jobs abbrechen und natürlich bestätigen, dass Sie über den richtigen Lebenszyklus verfügen, um Elemente Ihres Verzögerungsrückrufs zu berühren. Die Coroutines bieten auch stornierbare Aktionen an.

Erwähnenswert ist auch, dass Sie normalerweise mit den verschiedenen Ausnahmen umgehen sollten, die Coroutinen enthalten können. Zum Beispiel eine Stornierung, eine Ausnahme, ein Timeout oder was auch immer Sie verwenden möchten. Hier ist ein fortgeschritteneres Beispiel, wenn Sie sich wirklich für die Verwendung von Coroutinen entscheiden.

   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}")
            }
        }
2
Sam

Unten arbeitet man, wenn man bekommt,

Java.lang.RuntimeException: Kann keinen Handler in Thread erstellen, der hat Looper.prepare () nicht aufgerufen

final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);
2

Mit CountDownTimer..__ ist es sehr einfach. Weitere Informationen https://developer.Android.com/reference/Android/os/CountDownTimer.html

import Android.os.CountDownTimer;

// calls onTick every second, finishes after 3 seconds
new CountDownTimer(3000, 1000) { 

   public void onTick(long millisUntilFinished) {
      Log.d("log", millisUntilFinished / 1000);
   }

   public void onFinish() {
      // called after count down is finished
   } 
}.start();
2
Abdul Rizwan

Hier ist eine andere knifflige Methode: Es wird keine Ausnahme ausgelöst, wenn die ausführbaren Elemente der Benutzeroberfläche geändert werden.

public class SimpleDelayAnimation extends Animation implements Animation.AnimationListener {

    Runnable callBack;

    public SimpleDelayAnimation(Runnable runnable, int delayTimeMilli) {
        setDuration(delayTimeMilli);
        callBack = runnable;
        setAnimationListener(this);
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        callBack.run();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
}

Sie können die Animation folgendermaßen aufrufen:

view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));

Animationen können an jede Ansicht angehängt werden.

1
cdytoby

jeder scheint zu vergessen, den Handler zu säubern, bevor er eine neue ausführbare Nachricht oder eine neue Nachricht darauf veröffentlicht. Andernfalls könnten sie sich möglicherweise ansammeln und schlechtes Verhalten verursachen.

handler.removeMessages(int what);
// Remove any pending posts of messages with code 'what' that are in the message queue.

handler.removeCallbacks(Runnable r)
// Remove any pending posts of Runnable r that are in the message queue.
1
Dan Alboteanu

Ich mag Dinge sauberer: Hier ist meine Implementierung, Inline-Code, der in Ihrer Methode verwendet werden soll 

new Handler().postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);
1
Joolah

Hier ist die Antwort in Kotlin du faul, faule Leute

Handler().postDelayed({
//doSomethingHere()
}, 1000)
1
Daniel Wilson

Mit Kotlin können wir Folgendes erreichen

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

In Android können wir unten Kotlin-Code schreiben, um die Ausführung einer Funktion zu verzögern

class MainActivity : AppCompatActivity() {

private lateinit var handler: Handler

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    handler= Handler()
    handler.postDelayed({
        doSomething()
    },2000)
}

private fun doSomething() {
    Toast.makeText(this,"Hi! I am Toast Message",Toast.LENGTH_SHORT).show()
}
}
0
Ahasan

Eine geeignete Lösung in Android: 

private static long SLEEP_TIME = 2 // for 2 second
.
.
MyLauncher launcher = new MyLauncher();
            launcher.start();
.
.
private class MyLauncher extends Thread {
        @Override
        /**
         * Sleep for 2 seconds as you can also change SLEEP_TIME 2 to any. 
         */
        public void run() {
            try {
                // Sleeping
                Thread.sleep(SLEEP_TIME * 1000);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
            //do something you want to do
           //And your code will be executed after 2 second
        }
    }
0
Faakhir

Wenn Sie RxAndroid verwenden, wird die Behandlung von Threads und Fehlern wesentlich einfacher. Folgender Code wird nach einer Verzögerung ausgeführt

   Observable.timer(delay, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(aLong -> {
           // Execute code here
        }, Throwable::printStackTrace);
0
Supto

Es gibt viele Möglichkeiten, dies zu tun, aber das Beste ist, einen Handler wie den folgenden zu verwenden

long millisecDelay=3000

Handler().postDelayed({
  // do your work here
 },millisecDelay)
0
Shivam Yadav

Ähnliche Lösung, aber viel sauberer zu verwenden 

Schreibe diese Funktion außerhalb der Klasse

fun delay(duration: Long, `do`: () -> Unit) {

    Handler().postDelayed(`do`, duration)

}

Verwendungszweck:

delay(5000) {
    //Do your work here
}
0
Manohar Reddy

Für eine Verzögerung für die Nachbearbeitung einer einfachen Zeile können Sie Folgendes tun:

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

Ich hoffe das hilft

0
MrG