web-dev-qa-db-ja.com

定義された間隔でAndroidでRunnableスレッドを実行する方法

私はAndroidエミュレータの画面に一定の間隔でテキストを表示するアプリケーションを開発しました。私はHandlerクラスを使っています。これが私のコードの抜粋です。

handler = new Handler();
Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");               
    }
};
handler.postDelayed(r, 1000);

このアプリケーションを実行すると、テキストは一度だけ表示されます。どうして?

318
Rajapandian

あなたの例への簡単な修正は:

handler = new Handler();

final Runnable r = new Runnable() {
    public void run() {
        tv.append("Hello World");
        handler.postDelayed(this, 1000);
    }
};

handler.postDelayed(r, 1000);

あるいは、通常のスレッドを使用することもできます(オリジナルのRunnerを使用)。

Thread thread = new Thread() {
    @Override
    public void run() {
        try {
            while(true) {
                sleep(1000);
                handler.post(this);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

thread.start();

実行可能なオブジェクトをメッセージキューに送信して実行できるコマンドと見なし、handlerをそのコマンドを送信するためのヘルパーオブジェクトと見なすことができます。

詳細はこちら http://developer.Android.com/reference/Android/os/Handler.html

496
alex2k8

私は毎秒正しい更新のためのAlex2k8の最初の解決策を向上させることができると思います

1.オリジナルコード:

public void run() {
    tv.append("Hello World");
    handler.postDelayed(this, 1000);
}

2.分析

  • 上記のコストで、表示500倍の遅延時間が500 * Tミリ秒の後、tv.append("Hello Word") cost Tミリ秒と仮定します。
  • 長時間走ると遅れて増える

3.解決策

それを回避するにはpostDelayed()の順序を変更するだけで、遅延を回避できます。

public void run() {
    handler.postDelayed(this, 1000);
    tv.append("Hello World");
}
40
NguyenDat
new Handler().postDelayed(new Runnable() {
    public void run() {
        // do something...              
    }
}, 100);
37
user2212515

繰り返し作業に使用できます

new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);

いいね

new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {

            }
        },500,1000);

上記のコードは、最初にhalf second(500)の後に実行され、各second(1000)の後に繰り返されます

どこで

taskは実行されるメソッドです

after最初の実行までの時間

間隔繰り返し実行時間)

二番目に

また、タスクを何度も実行したい場合は、CountDownTimerを使用することもできます。

    new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval

     public void onTick(long millisUntilFinished) {
      }
      public void onFinish() {
     }
    }.start();

//Above codes run 40 times after each second

そして、あなたはまたrunnableでそれをすることができます。のような実行可能なメソッドを作成する

Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {

        }
    };

そして両方の方法でそれを呼びなさい

new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis  // to work on mainThread

OR

new Thread(runnable).start();//to work in Background 
23
Xar E Ahmer

私はこの典型的なケース、すなわち一定の間隔で何かを走らせるためには、Timerがより適切であると思います。これは簡単な例です:

myTimer = new Timer();
myTimer.schedule(new TimerTask() {          
@Override
public void run() {
    // If you want to modify a view in your Activity
    MyActivity.this.runOnUiThread(new Runnable()
        public void run(){
            tv.append("Hello World");
        });
    }
}, 1000, 1000); // initial delay 1 second, interval 1 second

Timerを使用することにはいくつかの利点があります。

  • 初期遅延と間隔はschedule関数の引数で簡単に指定できます
  • myTimer.cancel()を呼び出すだけでタイマーを止めることができます。
  • スレッドを1つだけ実行したい場合は、myTimer.cancel() before を新しいスレッドのスケジューリングの前に呼び出してください(myTimerがnullでない場合)。
23
iTech
Handler handler=new Handler();
Runnable r = new Runnable(){
    public void run() {
        tv.append("Hello World");                       
        handler.postDelayed(r, 1000);
    }
}; 
handler.post(r);
16
singh arjun

Handler.post()メソッドの説明を正しく理解できたら

Runnable rをメッセージキューに追加します。ランナブルは、このハンドラがアタッチされているスレッド上で実行されます。

そのため、@ alex2k8が提供する例は、正しく機能していても同じではありません。 Handler.post()が使用されている場合、 新しいスレッドは作成されません EDT によって実行されるRunnableを使用して、スレッドにHandlerをポストするだけです。その後、EDTはRunnable.run()のみを実行し、それ以外は実行しません。

覚えておいてください:Runnable != Thread

3
Damian Walczak

興味深い例は、カウンタ/ストップウォッチが別のスレッドで継続的に実行されているのを確認できることです。 GPS位置情報も表示します。主な活動の間、ユーザーインターフェーススレッドはすでにそこにあります。

抜粋:

try {    
    cnt++; scnt++;
    now=System.currentTimeMillis();
    r=Rand.nextInt(6); r++;    
    loc=lm.getLastKnownLocation(best);    

    if(loc!=null) { 
        lat=loc.getLatitude();
        lng=loc.getLongitude(); 
    }    

    Thread.sleep(100); 
    handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {   
    Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}

コードを見るにはここを見てください。

メインアクティビティのユーザーインターフェーススレッドと並んで走行可能なGPS位置と現在時刻を表示するスレッドの例

1

kotlinでは、このようにしてスレッドを実行できます。

class SimpleRunnable: Runnable {
    public override fun run() {
        println("${Thread.currentThread()} has run.")
    }
}
fun main(args: Array<String>) {
    val thread = SimpleThread()
    thread.start() // Will output: Thread[Thread-0,5,main] has run.
    val runnable = SimpleRunnable()
    val thread1 = Thread(runnable)
    thread1.start() // Will output: Thread[Thread-1,5,main] has run
}
0
Andreh Abboud

コトリン

private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
    val handler = Handler()
    runnable = Runnable {
        // do your work
        handler.postDelayed(runnable, 2000)
    }
    handler.postDelayed(runnable, 2000)
}

Java

Runnable runnable;
Handler handler;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    handler = new Handler();
    runnable = new Runnable() {
        @Override
        public void run() {
            // do your work
            handler.postDelayed(this, 1000);
        }
    };
    handler.postDelayed(runnable, 1000);
}
0
Khemraj