web-dev-qa-db-ja.com

Androidで遅れてメソッドを呼び出す方法

指定された遅延の後に次のメソッドを呼び出せるようにしたいです。 Objective Cでは、次のようなものがありました。

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

JavaとAndroidのこのメソッドに相当するものはありますか?たとえば、5秒後にメソッドを呼び出せるようにする必要があります。

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

コトリン

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


Java

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


1642
kontinuity

私の場合、他の答えはどれも使えなかった。代わりにネイティブのJavaタイマーを使用しました。

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

注: この答えは、質問で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);
  ⋮
}
180
erickson

5秒後にUIスレッドで何かを実行する場合

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

あなたは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);

    }
});
38
Hossam Ghareeb

すべての素晴らしい答えをありがとう、私は自分のニーズに最も合う解決策を見つけました。

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

このデモを見てください。

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

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つの方法です。

21
noob

私はView.postDelayed()メソッドを使用することを好みます、以下の簡単なコード:

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

これが私の最短の解決策です:

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

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);
8
vovahost

Timer をお勧めします、それはあなたが非常に特定の間隔で呼ばれるメソッドをスケジュールすることを可能にします。これはあなたのUIをブロックすることはなく、メソッドが実行されている間あなたのアプリを応答性の高い状態に保ちます。

他のオプションは wait()です。 method、これは現在のスレッドを指定された時間ブロックします。これにより、UIスレッドでこれを実行すると、UIが応答しなくなります。

6
Nate

KotlinJava多くの方法

1. Handlerを使う

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

2. TimerTaskを使う

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

あるいはもっと短い

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

それとも最短だろう

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

3. Executorsを使う

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

Javaで

1. Handlerを使う

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

2. Timerを使う

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

3. 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

あなたは最も簡単な解決策のためにこれを使うことができます:

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
5

新しく導入されたラムダ式を使用することで、よりクリーンにすることができます。

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

これを呼び出すためのもっと簡単なメソッドを作成しました。

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");を呼び出してください。

3
HelmiB

下のものがあなたが手に入れた時に働きます、

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);
3

だからこの猫を肌にするための非常に多くの方法があるので、ここで考慮すべきことがいくつかあります。答えはすべて選択され選択されていますが。 「大多数が簡単な答えを選んだ」という理由だけで誰かが間違った方向に進むのを防ぐために、これを適切なコーディングガイドラインで再検討することが重要だと思います。

それで最初に、このスレッドで全体的に勝者が選択した回答である単純な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}")
            }
        }
2
Sam

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();
2
Abdul Rizwan

単純ライン処理後処理遅延の場合、以下のようにすることができます。

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

これが役立つことを願っています

2
MrG

これは別のトリッキーな方法です:ランナブルが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));

アニメーションはどのビューにも添付できます。

1
cdytoby

誰もが新しいランナブルやメッセージを投稿する前にハンドラをきれいにするのを忘れているようです。そうでなければ、それらは潜在的に蓄積し、悪い行動を引き起こす可能性があります。

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

私は物事がきれいです:これが私の実装です、あなたのメソッドの中で使うインラインコード

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

これが答えです Kotlinでは怠惰な人、怠惰な人:

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

Kotlinを使用して、以下を実行することで達成できます。

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

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()
}
}
0
Ahasan

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

RxAndroidを使用すると、スレッドとエラーの処理がずっと簡単になります。以下のコードは、遅れて実行されます。

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

これを行う方法はたくさんありますが、最良の方法は以下のようなハンドラを使用することです。

long millisecDelay=3000

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

同様のソリューションですが、使用するのがはるかにきれいです

この関数をクラスの外側に記述します

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

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

}

使用法:

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