Android SDK WG 第1回 セッション(2008.10.25)?

実施要綱

  • 日時: 2008年10月25日(土曜日) 15:30 - 17:30
  • 場所: 新宿三井ビル (西新宿) 豆蔵セミナールーム

タイムライン

  • 15:30 - 16:00 参加者の自己紹介
  • 16:00 - 17:30 Activityのお勉強

EclipseからSDKのソースを参照する方法

ADTで作成したAndroid Projectからデフォルトで参照されているAndroid Libraryに対してソースコードの格納場所を明示的に指定することは不可能。Android SDKがあるディレクトリの下にsourcesと言うディレクトリを作成し、その下にソースのパッケージを放り込むと、Eclipseからも参照できるようになります。シンボリックリンクでもいけるでしょう。ただし、クラスによってはソースが存在していてもEclipse上からは参照できないものもあります。

Activityのライフサイクル(JavaDocより)

flow.png

Activityの各ライフサイクルメソッドの解説(JavaDocより)

メソッド説明Killable?Next
entirevisibleforeground
onCreateアクティビティのインスタンスが生成されるときに呼び出されます。UIの設定や、データのバインドなど、その画面を表示するために必要な初期処理をここで行ないます。また、以前に保存しておいた情報をBundleとして受け取ることが出来ます。NoonStrart
onRestart以前にストップされていた(onStopメソッドが呼ばれた)アクティビティが、再び動き出すときに呼び出されます。このメソッドの次にはonResumeメソッドが呼ばれます。NoonStrat
onStartアクティビティがユーザーの目に見えるようになるときに呼び出されます。もしアクティビティが最初に生成されたときは、次にonResumeメソッドが呼ばれます。もし以前にストップしたアクティビティが再表示されたときには、次にonRestartメソッドが呼ばれます。NoonResume,onStop
onResumeアクティビティがユーザーとやり取りできる状態になったときに呼び出されます。このメソッドが呼び出されたアクティビティは画面の最前面(アクティビティスタックのトップ)にあり、ユーザーからの入力を受け付けます。この状態にいるときに、別のアクティビティが、このアクティビティよりも前面に表示されようとした場合、onPauseメソッドが呼ばれます。NoonPause
onPause別のアクティビティが最前面で再開する前などに呼び出されるメソッドです。ここでは、未保存の変更情報を永続化したり、CPUを使用しているアニメーション処理などを停止します。なお、このメソッドの実行が完了するまで他のアクティビティは再開されないため、このメソッド内の処理は速やかに完了するようにします。このアクティビティが再び前面に表示されるときには、次にonResumeメソッドが呼ばれます。このアクティビティが完全にユーザから隠れてしまうときは、onStopメソッドが呼ばれます。YesonResume,onStop
onStopアクティビティが完全にユーザーの目に見えなくなったときに呼び出されます。このアクティビティが、再び前面に復帰するときには、onStartメソッドが呼ばれます。また、このアクティビティが完全に消滅するときには、onDestroyメソッドが呼ばれます。YesonRestart,onDestroy
onDestroyアクティビティが完全に終了する直前に呼び出されます。自らfinishメソッドを呼び終了させる場合と、システムが領域を確保するために終了させられる場合がありますが、それらはisFinisingメソッドで判断することが出来ます。Yesなし

主要シークエンス

Zygote初期化

1.jpg

Activity起動

2.jpg

onCreate時

3.jpg

Windowのフォーカスイベント(概要)

4.jpg

onStop時

5.jpg

シークエンスに関する補足

  • ZygoteInit -> ZygoteConnection -> Zygote -> forkexecされる過程は通常のソケットプログラミングのお作法と一緒
  • Looperはスレッドローカルですよ
  • Looperのスレッド = UIThread(ActivityのmThread)ですよ
  • Looperのメッセージループ内で処理されるMessageのtargetは常にHandlerのみ。Handler重要。ActivityThread$Hとか。

ActivityのJavaDocに関する他のトピック(JavaDocの適当な意訳です)

onSaveInstanceState

onSaveInstanceState(Bundle)メソッドは、Activityが背面に行く前に呼ばれます。引数のBundleの中に、動的なインスタンスの状態を何でも退避させることが出来ます。で、後でもしアクティビティが再生成されることがあったら、onCreate(Bundle)メソッドで受け取ることが出来ます(詳細はプロセスライフサイクルのセクションを見てね)。注意してほしいのは、永続的に保持したいデータはonSaveInstanceStateではなくonPauseで保存してってことです。"後で"、というのは、ライフサイクルのコールバックの一部というわけではないので、このドキュメントで触れているような全ての状況で呼ばれるわけじゃないからです。

コンフィグレーションの変更

デバイスのコンフィグレーションが変更されたら、UIはそのコンフィグレーションにマッチするように更新する必要があります。Activityはユーザーとインタラクトするための基本的な仕組みなので、コンフィグレーションの変更を取り扱えるようになっています。通常は、コンフィグレーション(画面の向き、入力デバイス、言語など)が変更されると、Activityは、ライフサイクルプロセス(onPause(), onStop(), そして onDestroy() )に従って終了します。もしそのActivityがforegroundやvisibleだった時は、一度onDestroyが呼ばれてから、新たなインスタンス(前のインスタンスがonSaveInstanceStateメソッドで作ったsavedInstanceを伴って)が作られます。なぜこのようになっているかと言うと、どんなアプリケーションリソース(レイアウトファイルも含みます)もコンフィグレーションの値に依存しているかもしれないからです。コンフィグレーションの変更に安全に対処する唯一の方法は、layoutやdrawableやstringも含めた全てのリソースをもう一度取得しなおすことです。Activityは、今のUIの状態を保存したり、その保存された状態から自分自身の状態を復元したりする方法を既に知っているはずなので、新しいコンフィグレーションでActivityに自分自身を再スタートさせるって方法は都合がいいです。  特別なケースでは、コンフィグレーションの変更があってもActivityの再スタートを避けたいこともあるかもしれません。こんなときはマニフェストにandroid:configChanges属性を追加してください。ここで宣言した種類のコンフィグレーションの変更があると、アクティビティは再スタートされる代わりにonConfigurationChangedが呼ばれます。ただし、コンフィグレーションの変更の中に、ここで宣言していないものが含まれていたら、やっぱりActivityは再スタートしてしまいます。(onConfigurationChangedは呼ばれないでしょう。)

その他モロモロ

コンフィグの変更ってどうやって発生させる?

いちばん簡単なのは、画面のlandscape mode(横長)とportrait mode(縦長)を切り替えること(ctrl + F12)です。このときは、orientationとkeyboardHiddenのふたつのコンフィグ値が変更になるので気をつけて下さい。このようにキーボードの出し入れがlandscape modeとportrait modeの切り替えと連動している時点で、エミュレータは明らかにG1を意識しています。iPhoneのように傾度で変更する端末もあるでしょうが、そういう端末とはエミュレータの挙動が異なると言うことになります。

Viewの幅など、画面系のプロパティが取れるのは?

onWindowFocusChangedのときです。onResumeよりも後です。Viewがレンダリングされていないと取れません。

onConfigurationChangedで、Viewの幅などを取ると、前の古い値になるが?

onConfigurationChangedはコンフィグの変更があった時にすぐに呼ばれてそう

  • ActivityThread#handleRelaunchActivity - >handleConfigurationChanged -> performPauseActivity -> handleDestroyActivity -> handleLaunchActivity・・・
  • ActivityThread$H#handleMessage -> handleActivityConfigurationChanged -> performConfigurationChanged ・・

なので、Viewのレンダリング前だから画面系のオブジェクトは古いコンフィグ時の値になりそうです。(もちろんパラメータとして渡されるConfigurationは、新しいコンフィグの値が渡ってきています)