search
LoginSignup
71

More than 1 year has passed since last update.

posted at

updated at

AndroidでTimerを使わずHandlerだけでお手軽に定期実行してあげる

UIスレッドの処理をTimerを使わずHandlerだけで簡単定期実行したい

『1秒間隔で定期的に何かの処理を行う』という実装を行う際、パッと思いつくのはTimerとTimerTaskを使った以下のような実装。
ただ、その際TimerTask.run()の中で実行されるコードはTimerのThreadなので、
UIパーツへの操作など、UIスレッドで実行が必要な操作をするにはHandlerを使う必要があります。

課題

そうなると、

  1. UIスレッドがTimerを実行
  2. TimerスレッドがUIスレッドに返す
  3. UIスレッドでdoSomething実行

みたいな、ちょっとわかりづらい処理になってしまいます。

コードだとこんな感じが必要になります。
(ネストが深いですが、処理のループがわかりやすいので、そのまま。)

Before


final Handler handler = new Handler();
TimerTask task = new TimerTask() {
    int count = 0;    
    @Override
    public void run() {
        // Timerのスレッド
        handler.post(new Runnable() {
            @Override
            public void run() {
                // UIスレッド
                if (count > 5) { // 5回実行したら終了
                    cancel();
                }
                doSomething(); // なにかやる
                count++;
            } 
        });
    }
};
Timer t = new Timer();
t.scheduleAtFixedRate(task, 0, 1000);

対策

TimerとTimerTaskがほとんど何もやってない感じなので、その2クラスを消したいです。
HandlerのpostDelayedを使うと、Timer・TimerTaskを削除して、定期実行することができるようになります。

After


final Handler handler = new Handler();
final Runnable r = new Runnable() {
    int count = 0;
    @Override
    public void run() {
        // UIスレッド
        count++;
        if (count > 5) { // 5回実行したら終了
            return;
        }
        doSomething(); // 何かやる
        handler.postDelayed(this, 1000);
    }
};
handler.post(r);

キャンセルしたいときは
handler.removeCallbacks(r);
で、runnableとの関係を切ってあげればOKです。

割と直感的なコードになりました。
この程度であればお手軽にUIスレッドでも定期実行できそうです。

参考

TIMER(TASK) = BAD! DO IT THE ANDROID WAY: USE A HANDLER

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
71