Androidを支える技術<II> 5.3, 5.4章
日付:3/28
章:5.3, 5.4
調査者:ichimura.icon
章のまとめ
どんな内容が書かれているか?
ActivityThreadの役割
ActivityThreadのmain()メソッドの詳細
ApplicationThreadの概要
ActivityThreadの3つの重要なメソッド
main()
アプリのプロセスが生成されて最初に呼ばれ、アプリ処理の起点となるメソッド
attach()
白紙のプロセスをapkのアプリに置き換えるメソッド
handleMassage()
メッセージを処理するメソッド
SDKのServiceのライフサイクルに関わる処理を行う
ActivityThreadの役割
アプリのプロセスのエントリポイント
ActivityThread.main()で呼び出され、最初に起動する。
ActivityManagerServiceとアプリのプロセスとのインターフェース
ActivityThreadとやり取りしながらアプリのプロセスを操作する
ActivityやSDKのServiceの、ライフサイクル関連の処理を実際に行うクラス
アプリのプロセス側で実際の処理を行うクラス
ActivityのonStart()などのコールバックを呼ぶのもこのクラス
UIスレッドを表すオブジェクト
1.4.1の「Looperのloop()を呼んだスレッドがUIスレッドになる」がこれ
アプリのapkのクラスをロードして実行するクラス
ActivityTreadの構成要素とmain()メソッド
code:ActivityThread
public static void main(String[] args) {
// Looperの初期化処理。1.4.1項を参照
Looper.prepareMainLooper();
// ActivityThreadのインスタンスを作って、ActivityManagerServiceと接続する
ActivityThread thread = new ActivityThread();
thread.attach(false);
// メッセージループ。このループは無限ループ。1.4.1項を参照
Looper.loop();
// ここには永遠に来ない
}
ActivityThreadのmain()メソッドの要所は、Looper周辺の処理とActivityThreadのインスタンス生成処理の2箇所
Looper周辺の処理
LooperのprepareMainLooper()で初期化、Looperを用いてloop()を実行し、ループを回す
loop()を呼び出すスレッドはUIスレッド
UIスレッドは、ActivityThreadのmain()を実行するスレッドであり、アプリのプロセスがforkした時に最初に実行されるスレッド
ActivityThreadのインスタンス生成
LooperのprepareMainLooper()やloop()メソッドが呼ばれるスレッドと同じスレッドで呼ばれる
TLSを暗黙のうちの参照することが多いLooper-Handler周辺では重要なポイントとなる ActivityThreadの2つの内部クラス
ActivityThreadには2つの重要な内部クラスがある
HandlerのサブクラスH
BinderのサブクラスのApplicationThread
H
ActivityThreadのフィールド初期化のタイミングでコンストラクタが呼ばれる
つまり、ActivityThreadのmain()を呼び出すスレッドと同じスレッド
HandlerはnewされたスレッドのTLSにあるLooperと関連付けられる(1.4.2参照) つまり同じスレッドで動くLooper.prepareMainLooper()のLooperと関連付けられる
code:H.java
private class H extends Handler {
// メッセージIDの定義
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
...
// メッセージ処理のためhandleMessage()をオーバーライド
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
...
sendMassage()を呼び出すことで、handleMassage()で処理を行うようにメッセージを送信できる
handleMassage()を持つクラスHはActivityThreadでコンストラクタが呼ばれる
よってHはUIスレッドで処理を行うように依頼するHandlerとなる
UIスレッドで行う処理を、オーバーライドしたhandleMassage()に書くことでUIスレッド以外からUIスレッドで行う処理を依頼できる
ApplicationThread
Binder越しに外部のプロセスからActivityThreadのメソッドを呼ぶためだけに存在するクラス
ApplicationThreadはBinderスレッドプールからの呼び出しとなる
UIスレッドとは別スレッドからの呼び出しとなる
サービスプロキシ越しに、別プロセスであるAcitivityManagerServiceから呼ばれる
基本的に行うことはHのインスタンスにメッセージを投げるだけ
実際の処理はhandleMessage()から呼ばれるhandleXX系列のメソッド側で行われる
実際の処理はしてないということを示すため、メソッド名は「schedule」から始まる決まりとなっている
参考 図5.2
code:ApplicationThread.java
public final class ActivityThread {
...
// 内部クラスのApplicationThreadの定義“定義
private class ApplicationThread extends ApplicationThreadNative {
// scheduleで始まるメソッド。基本的にはmHのsendMessageを呼ぶだけ
public final void scheduleDestroyActivity(IBinder token, boolean finishing,
int configChanges) {
// ❶Messageの初期化
Message msg = Message.obtain();
msg.what = H.DESTROY_ACTIVITY; // DESTROY_ACTIVITYはfinal intで109
msg.obj = token;
msg.arg1 = finishing ? 1 : 0;
msg.arg2 = configChanges;
// ❷mHはHandlerのサブクラス
mH.sendMessage(msg);
}
...
}
scheuleDestroy()メソッドの動き
1. でメッセージを初期化を初期化
2. のsendMassage()で送信する
ApplcationThreadは外部プロセスとのインターフェースとも言える
scheduleXX()は、ActivityThreadでhandleXX()に対応しているので、処理を追うときはそれを辿っていく
応用
code:sample.kt
質疑応答