タイマー割り込みを使う
もう1つ、毎秒ごとに画面を更新させる部分を解説しておきましょう。以前解説したように(関連記事)アプリケーションはActivityでできており、Activityには、特定の状態遷移があります。アプリケーションが動作していても、他のアプリケーションが起動してバックグラウンドになることもあるし、メモリから追い出されてしまうこともあります。こうしたタイミングは、onResumeやonPauseで検出することができます。
アプリケーションは、onCreateを実行したあと必ずonResumeを通り、画面が切り替わるときにはonPauseを通ります。このonResumeとonPauseは、他の場合にも通るルートなので、この2ヵ所でアプリケーションがフォアグランドなのかそうでないのかを検出することができるわけです。「世界時計サンプル」は時計なので、表示されている間は更新され続ける必要がありますが、バックグラウンドになっている間は動く必要(表示を変える)はありません。そこで、onResumeでタイマーをオンにして、一定期間ごとに画面を更新するようにして、onPauseでこれを止めるようにします。
Javaでは、タイマーによる周期的な実行にTimerオブジェクトを使います。このTimerオブジェクト自体は、Javaの標準オブジェクトなので、Androidとは無関係ですが、Androidアプリケーション内にあるメソッドを実行させるためには、ちょっとした仕組みが必要です。というのはAndroidでは、画面更新などはアプリケーションのコードが止まっている間に動くようになっているからです。たとえば、Toastの出力のあとにコードを実行させると、Toastが表示されなくなってしまいます。また、第8回で解説したProgressDialogでも別スレッドを作ったのは(関連記事)、アプリケーションのスレッドと切り替えて動作するGUIスレッドのためです。
このときに使うのがHnadlerで、これはGUI側のスレッドが管理するキューに、処理したいオブジェクトを入れ、GUI側が順番にキューにあるオブジェクトを実行するという仕組みです。では細かくみていくことにしましょう。まずはonResumeです。ここは、どのような場合でも、アプリケーションが起動または再開するときに必ず通るメソッドです。WorldClock.javaでは、327行目からになります。
@Override
protected void onResume() {
super.onResume();
timer = new Timer(true);
timer.schedule(
new TimerTask(){
public void run(){
handler.post(new Runnable(){
public void run(){ refresh(); }
});
}
}
, 1000, 1000);
}
まず、Timerオブジェクトを作り、そこにscheduleメソッドで、TimerTaskを登録します。scheduleメソッドは、
public void schedule (TimerTask task, long delay, long period)
となっており、3つの引数のうち、最初が実行すべきTimerTask、次が遅延(最初の実行までの待ち時間)、最後がくり返し周期です。ここでは、遅延とくり返し周期に1000を指定してあり、単位はミリ秒なので1秒となっています。時計なので、本来なら最初の遅延は、現在のミリ秒を取得して零秒ぴったりに合わせる必要があるのですが、1秒以下の誤差はいいだろうということで初期値はそのままにしてあります。
TimerTaskオブジェクトは、コードにあるようにここで生成されています。TimerTaskオブジェクトはrunメソッドがあり、Timerから実行されるときには、このメソッドが呼び出されます。
このrunメソッドの中にあるのが、postメソッドです。handler自体は、worldclcokアクティビティのプライベート変数として先頭付近で定義されています。
postメソッドは、Runnableオブジェクトを引数とします。やはりRunnableオブジェクトも内部にあるrunメソッドに実行したい処理を記述します。
オブジェクトがネストしていますが、Handlerにポストされる処理は、refreshメソッドの呼び出しだけです。HanderをTimeTask内で直接書かないだけでやっていることは単純です。
次に、アクティビティが停止または中断するときに通過するonPauseメソッドを見ます。これは、WorldClock.javaの320行目にあります。
@Override
protected void onPause() {
super.onPause();
timer.cancel();
timer.purge();
}
ここでやっているのは、タイマーを止めて、スケジュールされているタスクを取り消しています。その後、purgeでタスクキューからタスクを消去させています。purgeの説明では「Removes all canceled task from the task queue」となっているので、さきにcancelしておく必要があるようです。
さて、これで、Android開発の大きなポイントは解説したので、次回は実際に作成したアプリをAndroidマーケットへ登録するまでを紹介する予定です。
この連載の記事
-
第11回
スマホ
アプリケーションをAndroidマーケットに登録する -
第9回
スマホ
Androidアプリで複数の項目を表示するリストビューを使う -
第8回
スマホ
Androidアプリに必要なダイアログを作る -
第7回
スマホ
Androidアプリの設定画面を作成する -
第6回
スマホ
Androidアプリ内で表示されるメニューを作成する -
第5回
スマホ
インテントによるアプリケーションとアクティビティの呼出し -
第4回
スマホ
Androidアプリを構成する「アクティビティ」を実際に作る -
第3回
スマホ
アプリケーションの基本となる「アクティビティ」 -
第2回
スマホ
開発したアプリをエミュレーターやデバッガ上でテストする -
第1回
スマホ
Androidアプリの開発環境であるEclipseの使い方を知る - この連載の一覧へ