指定された遅延の後に次のメソッドを呼び出せるようにしたいです。 Objective Cでは、次のようなものがありました。
[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];
JavaとAndroidのこのメソッドに相当するものはありますか?たとえば、5秒後にメソッドを呼び出せるようにする必要があります。
public void DoSomething()
{
//do something here
}
Handler().postDelayed({
//Do something after 100ms
}, 100)
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
私の場合、他の答えはどれも使えなかった。代わりにネイティブのJavaタイマーを使用しました。
new Timer().schedule(new TimerTask() {
@Override
public void run() {
// this code will be executed after 2 seconds
}
}, 2000);
注: この答えは、質問でAndroidがコンテキストとして指定されていない場合に出されました。 AndroidのUIスレッド固有の回答については こちらをご覧ください。
Mac OS APIは現在のスレッドを続行させ、タスクを非同期的に実行するようにスケジュールします。 Javaでは、同等の機能がJava.util.concurrent
パッケージによって提供されます。 Androidがどのような制限を課す可能性があるのかわかりません。
private static final ScheduledExecutorService worker =
Executors.newSingleThreadScheduledExecutor();
void someMethod() {
⋮
Runnable task = new Runnable() {
public void run() {
/* Do something… */
}
};
worker.schedule(task, 5, TimeUnit.SECONDS);
⋮
}
5秒後にUIスレッドで何かを実行する場合
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
//Do something here
}
}, 5000);
あなたはUIThreadの中でHandlerを使うことができます:
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);
}
});
すべての素晴らしい答えをありがとう、私は自分のニーズに最も合う解決策を見つけました。
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
}
}
このデモを見てください。
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?");
}
}
Handlerを使用する必要があるが、別のスレッドにいる場合は、runonuithread
を使用してUIスレッドでハンドラを実行できます。これはLooper.Prepare()
を呼ぶように頼まれる投げられる例外からあなたを救うでしょう
runOnUiThread(new Runnable() {
@Override
public void run() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 1 second
}
}, 1000);
}
});
かなり乱雑に見えますが、これは1つの方法です。
私はView.postDelayed()
メソッドを使用することを好みます、以下の簡単なコード:
mView.postDelayed(new Runnable() {
@Override
public void run() {
// Do something after 1000 ms
}
}, 1000);
これが私の最短の解決策です:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
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);
Android Studio 3.0 以上を使用している場合は、ラムダ式を使用できます。メソッドcallMyMethod()
は2秒後に呼び出されます。
new Handler().postDelayed(() -> callMyMethod(), 2000);
遅延ランナブルをキャンセルする必要がある場合は、これを使用してください。
Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);
// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);
Kotlin
&Java
多くの方法
Handler
を使うHandler().postDelayed({
TODO("Do something")
}, 2000)
Timer().schedule(object : TimerTask() {
override fun run() {
TODO("Do something")
}
}, 2000)
あるいはもっと短い
Timer().schedule(timerTask {
TODO("Do something")
}, 2000)
それとも最短だろう
Timer().schedule(2000) {
TODO("Do something")
}
Executors
を使うExecutors.newSingleThreadScheduledExecutor().schedule({
TODO("Do something")
}, 2, TimeUnit.SECONDS)
Javaで
Handler
を使うnew Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something
}
}, 2000);
Timer
を使うnew Timer().schedule(new TimerTask() {
@Override
public void run() {
// Do something
}
}, 2000);
ScheduledExecutorService
を使うprivate static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run() {
// Do something
}
};
worker.schedule(runnable, 2, TimeUnit.SECONDS);
あなたは最も簡単な解決策のためにこれを使うことができます:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Write your code here
}
}, 5000); //Timer is in ms here.
そうでなければ、以下は別のきれいな便利な解決策になることができます:
new Handler().postDelayed(() ->
{/*Do something here*/},
5000); //time in ms
新しく導入されたラムダ式を使用することで、よりクリーンにすることができます。
new Handler().postDelayed(() -> {/*your code here*/}, time);
これを呼び出すためのもっと簡単なメソッドを作成しました。
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);
}
それを使うには、単に.CallWithDelay(5000, this, "DoSomething");
を呼び出してください。
下のものがあなたが手に入れた時に働きます、
Java.lang.RuntimeException:Looper.prepare()を呼び出していないハンドラをスレッド内に作成できない
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
だからこの猫を肌にするための非常に多くの方法があるので、ここで考慮すべきことがいくつかあります。答えはすべて選択され選択されていますが。 「大多数が簡単な答えを選んだ」という理由だけで誰かが間違った方向に進むのを防ぐために、これを適切なコーディングガイドラインで再検討することが重要だと思います。
それで最初に、このスレッドで全体的に勝者が選択した回答である単純なPost Delayed回答について議論しましょう。
考慮すべきことがいくつかあります。ポスト遅延の後、あなたはメモリリーク、死んだオブジェクト、消えたライフサイクルなどに遭遇する可能性があります。そのため、適切に取り扱うことも重要です。いくつかの方法でこれを行うことができます。
現代の発展のために、私はKOTLINで供給します
これは、コールバックでUIスレッドを使用し、コールバックを実行したときにアクティビティがまだ有効であることを確認する簡単な例です。
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
ただし、アクティビティがなくなった場合にコールバックを実行する理由はないため、これはまだ完璧ではありません。そのため、もっと良い方法は、それへの参照を保持し、このようなコールバックを削除することです。
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)
}
}
そしてもちろんonPauseのクリーンアップを処理してコールバックに当たらないようにします。
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
これまで説明してきたので、現代のコルーチンとkotlin :)を使用して、よりクリーンなオプションについて説明しましょう。あなたがまだこれらを使っていないのなら、あなたは本当に見逃しています。
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
あるいは、そのメソッドで常にUIを起動したい場合は、次のようにします。
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
もちろん、PostDelayedと同じように、キャンセルを確実に処理しなければならないので、遅延呼び出しの後にアクティビティチェックを実行するか、他のルートのようにonPauseでキャンセルすることができます。
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}")
}
}
}
}
//クリーンアップ処理
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
}
}
起動(UI)をメソッドシグネチャに入れると、呼び出し側のコード行でジョブを割り当てることができます。
だから物語の倫理はあなたの遅れた行動に安全であること、あなたがあなたのコールバックを削除すること、またはあなたの仕事をキャンセルすることを確実にすることである。コルーチンはまたキャンセル可能な行為を提供する。
また、通常コルーチンに含まれる可能性があるさまざまな例外を処理する必要があることも注目に値します。たとえば、キャンセル、例外、タイムアウトなど、使用することにしたものは何でも。あなたが本当にコルーチンを使い始めることに決めたならば、これはより高度な例です。
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}")
}
}
CountDownTimer
を使うのはとても簡単です。詳細については 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();
単純ライン処理後処理遅延の場合、以下のようにすることができます。
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Do someting
}
}, 3000);
これが役立つことを願っています
これは別のトリッキーな方法です:ランナブルがUI要素を変更するとき、それは例外を投げません。
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) {
}
}
あなたはこのようにアニメーションを呼ぶことができます:
view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));
アニメーションはどのビューにも添付できます。
誰もが新しいランナブルやメッセージを投稿する前にハンドラをきれいにするのを忘れているようです。そうでなければ、それらは潜在的に蓄積し、悪い行動を引き起こす可能性があります。
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.
私は物事がきれいです:これが私の実装です、あなたのメソッドの中で使うインラインコード
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 100ms
}
}, 100);
これが答えです Kotlinでは怠惰な人、怠惰な人:
Handler().postDelayed({
//doSomethingHere()
}, 1000)
Kotlinを使用して、以下を実行することで達成できます。
Handler().postDelayed({
// do something after 1000ms
}, 1000)
Androidでは、任意の機能の実行を遅らせるために以下のようにkotlinコードを書くことができます。
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()
}
}
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
}
}
RxAndroidを使用すると、スレッドとエラーの処理がずっと簡単になります。以下のコードは、遅れて実行されます。
Observable.timer(delay, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> {
// Execute code here
}, Throwable::printStackTrace);
これを行う方法はたくさんありますが、最良の方法は以下のようなハンドラを使用することです。
long millisecDelay=3000
Handler().postDelayed({
// do your work here
},millisecDelay)
同様のソリューションですが、使用するのがはるかにきれいです
この関数をクラスの外側に記述します
fun delay(duration: Long, `do`: () -> Unit) {
Handler().postDelayed(`do`, duration)
}
使用法:
delay(5000) {
//Do your work here
}