woshidan's blog

そんなことよりコードにダイブ。

java.util.TimerをAndroidで使ってみた場合

以前気になったので素振りした時のメモ。AndroidのバージョンはAPI 21です。

まとめ

  • Timer.schedule(TimerTask task, long delay, long interval)delay秒後から、前回のタスクと今回のタスクの実行開始時間の間隔がなるべくintervalになるように定期的にtaskを実行する 
  • Timerのコンストラクタで新しいスレッドが動き出し、定期的に実行されるタイマーのタスクは全てそのスレッドで実行される
  • Activity.onStopが呼び出されてアプリがバックグラウンドへ隠れてもTimerの処理は止まらない

参考:

簡単にコード書いてログで確認してみた

package com.example.woshidan.timertest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Timer timer = new Timer();
        final Random random = new Random();
        final List<Integer> list = new ArrayList<>();
        final long startTime = System.currentTimeMillis();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Log.d(Thread.currentThread().getName(), (System.currentTimeMillis() - startTime) + " ms. " + "n = " + list.size() + " start ");
                int wait = random.nextInt(1000);
                try {
                    Thread.sleep(wait + 1000); // アップロード処理の終了の代わりに適当にウェイト置いてる
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(Thread.currentThread().getName(), (System.currentTimeMillis() - startTime) + " ms. " + "n = " + list.size() + " end ");
                list.add(list.size());
            }
        }, 500, 3000);
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d("MainActivity", "onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("MainActivity", "onDestroy");
    }
}
// 定期的にリクエストされるタイマーのタスクは全て同じスレッドで実行される
D/Timer-0: 500 ms. n = 0 start 
D/Timer-0: 2218 ms. n = 0 end 
D/Timer-0: 3500 ms. n = 1 start // 前回と今回の間のstartの間隔はなるべく3秒間隔
D/Timer-0: 4896 ms. n = 1 end 
D/Timer-0: 6500 ms. n = 2 start 
D/Timer-0: 7733 ms. n = 2 end 
D/Timer-0: 9500 ms. n = 3 start 
D/Timer-0: 11096 ms. n = 3 end 
D/MainActivity: onStop // バックグラウンドになっても止まらない
D/Timer-0: 12500 ms. n = 4 start 
D/Timer-0: 14368 ms. n = 4 end 
D/Timer-0: 15530 ms. n = 5 start // 遅れることもある(前回分の実行に時間がかかったなど)
D/Timer-0: 17289 ms. n = 5 end 
D/Timer-0: 18568 ms. n = 6 start // そうするとその次で「前回と今回の間のstartの間隔はなるべく3秒間隔」を守るために、次以降も時間がずれたままになる
D/Timer-0: 19608 ms. n = 6 end 
D/Timer-0: 21608 ms. n = 7 start 
D/Timer-0: 23448 ms. n = 7 end 
D/Timer-0: 24645 ms. n = 8 start 
D/Timer-0: 26188 ms. n = 8 end 
D/Timer-0: 27678 ms. n = 9 start 
D/Timer-0: 29216 ms. n = 9 end 
D/Timer-0: 30718 ms. n = 10 start 
D/Timer-0: 32033 ms. n = 10 end 
D/Timer-0: 33744 ms. n = 11 start 
D/Timer-0: 34993 ms. n = 11 end