●タイマー

ある時間後に単発、もしくは、周期的に処理を実行します。
Threadで無限ループとsleepで同じことが出来たりしますが御好みの方で。

まずは実行の2秒後(2000ms)に音を鳴らすコードです。

java.util.TimerTask timertask = new java.util.TimerTask(){
    @Override
    public void run() {
        android.media.ToneGenerator tg;
        tg = new android.media.ToneGenerator(android.media.AudioManager.STREAM_SYSTEM, android.media.ToneGenerator.MAX_VOLUME);
        tg.startTone(android.media.ToneGenerator.TONE_DTMF_0,100);
    }
};
java.util.Timer timer = new java.util.Timer(true);
timer.schedule(timertask,(long)2000);

上のコードの赤文字部分が音を鳴らす処理になっています。
java.util.Timer timer = new java.util.Timer(true);
Timerのコンストラクタの引数にtrueを設定することによってメインスレッド終了時にタイマーも終了します。
もし、falseや引数を指定しないと、アプリケーションを終了しても、タイマーが終了しません。

一番下の行の引数に3番目の値を入れることによりその後の繰り返しの時間を指定することができます。
timer.schedule(timertask,(long)2000,(long)1000);
このようにすることにより最初の2秒後(2000ms)に処理が実行され、その後、1秒毎(1000ms)に処理が実行され続けます。


■メインスレッドで行う処理

タイマーで処理される部分は別スレッドで実行されます。
そのため、画面周りの処理などを実行しようとすると例外がスローされます
もし、画面周りなどの処理をメインスレッドで実行したい場合には、Handlerを使ってシステムに実行を予約する必要があります。
実行を予約することにより、メインスレッドの処理が空いたら順次実行されます。

java.util.TimerTask timertask = new java.util.TimerTask(){
    android.os.Handler handler = new android.os.Handler();
    @Override
    public void run() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                ((android.widget.Button) findViewById(R.id.button)).setText(""+i++);
            }
        });
    }
};
java.util.Timer timer = new java.util.Timer(true);
timer.schedule(timertask,(long)2000,(long)1000);
赤文字部分を追加する事により画面の更新などができるようになります。


■タイマーのキャンセル

タイマーのスケジュールをキャンセルするには、timer.cancel();をコールします。
しかし、タイマー自体も破棄されるため、再度スケジュールするには、再びnewし直す必要があります。


■アプリケーション終了時

Activityの終了直前のonDestroy()の中でtimer.cancel()をすると、画面が閉じた後で残念な結果になります。

このような感じで終了時エラーが出ます。


そこで、onResume()の中でタイマーを起動させて、onPause()の中でtimerの後始末をすると問題なく終了できます。
onResume()はActivityが表示された時に呼び出されて、onPause()はActivityが消える直前に呼び出されます。
onResume()とonPause()は一対のものと言えます。

timer.cancel()をするとTimerTaskも一緒に破棄されてしまいますので毎回新たにnewする必要があります。

private java.util.TimerTask timertask;

@Override
protected void onResume() {
    super.onResume();
    timertask = new java.util.TimerTask(){
        @Override
        public void run() {
        }
    };

    //タイマーの起動
    timer = new java.util.Timer(true);
    timer.schedule(timertask,(long)1000,(long)500);
}

@Override
protected void onPause() {
    super.onPause();
    //タイマーの後始末
    timer.cancel();
    timer.purge();
}

■タイマーの挙動

一つのタイマーに複数のスケジュールをして、一つのスケジュールに時間のかかる処理を入れてみると、 可能な限りスケジュールに従い実行されるように空き時間が短くなります。
また、スケジュールの遅れが次のスケジュールの開始時間を超えた場合には即座に実行されます。


オレンジと赤のスケジュールを1秒毎に実行されるようにして、オレンジのスケジュールが時間のかかる処理だった場合にはこのような挙動になります。
複数のタイマーを生成 new Timer(true) して個々のタイマーに対してスケジュールしている場合は、各々違うスレッドで実行されるためスケジュールの干渉はありません。


▲トップページ > android