Android Handlerソースコードの正しい姿勢をアーキテクチャの観点から分析する
Handlerの原理は何ですか?Handlerの実現メカニズムを深く分析できますか?面接官は、handlerのソースコード、handlerメカニズムがどのように実現されているのか、メッセージポンプLooperについて理解していない(より完全なプロジェクトがダウンロードされています.未完は続きます.ソースコード.図文の知識はgithubにアップロードされます).
1.Handlerメカニズムの概要Androidメッセージングメカニズムの定義 作用 マルチスレッドのアプリケーションシーンでは、作業スレッドでUIを更新する必要がある操作情報をUIマスタースレッドに伝達し、作業スレッドによるUIの更新処理を実現し、最終的に非同期メッセージの処理を実現する
Handlerを使用する理由:作業スレッドがUIを操作する必要があるというメッセージをメインスレッドに伝え、メインスレッドが作業スレッドの必要に応じてUIを更新できるようにし、スレッドの操作が安全でないという問題を回避する
2.知識の準備
以下の説明の中で、私は直接英文名を使って説明して、すなわち
2.2使用方法次のソース分析は使用手順に従って説明する 3.Handlerメカニズムのコアクラス
ソースコード分析の前に、
3.1類説明プロセッサクラス メッセージキュークラス 循環器類 4.ソース分析以下のソースコード解析は の2種類に分けられる.以下のソースコード解析は、上記2つの使用方法に従って 方式1:Handlerを用いる.sendMessage()
手順の使用ソース分析以下、上記各ステップに従ってソース分析 手順1:メインスレッドで匿名の内部クラスからHandlerクラスオブジェクトを作成する以上から分かるように、Handlerオブジェクトを作成すると、構築方法によって現在のスレッドのLooperオブジェクト&対応するメッセージキューオブジェクト(MessageQueue)が自動的に関連付けられ、Handlerオブジェクトの作成操作を実現するスレッド0が自動的にバインドされるようになると、現在のスレッドのLooperオブジェクト&対応するメッセージキューオブジェクト(MessageQueue)はいつ作成されますか?
上記の使用手順では、Looperオブジェクト&対応するメッセージキューオブジェクト(MessageQueue)を作成する手順はありません.
手順1までの暗黙的な操作1:ループオブジェクト(Looper)&メッセージキューオブジェクト(MessageQueue)の作成ソースコード分析
まとめ:メインスレッドを作成すると、
1.すなわち、メインスレッドの
Handlerの役割に従って(メインスレッドでUIを更新する)、したがってHandlerインスタンスの作成シーンは主にメインスレッド 生成
1.Handlerメカニズムの概要
Handlerを使用する理由:作業スレッドがUIを操作する必要があるというメッセージをメインスレッドに伝え、メインスレッドが作業スレッドの必要に応じてUIを更新できるようにし、スレッドの操作が安全でないという問題を回避する
2.知識の準備
Handler
メカニズムのソースコード分析を読む前に、Handler
のいくつかの備蓄知識を理解してください:関連概念、使用方法&動作原理######2.1関連概念Handler
メカニズムに関する概念は以下の通りである.以下の説明の中で、私は直接英文名を使って説明して、すなわち
Handler
、Message
、Message Queue
、Looper
、Handler
を使って、みんなが先に関連概念を熟知することを望みます2.2使用方法
Handler.sendMessage()
使用方法は、メッセージキューにメッセージを送信する方法によって異なり、使用 Handler.post()
、Handler
ソースコード分析の前に、
Handler
メカニズムのコアクラスを理解します.3.1類説明
(Handler)
メカニズムには3つの重要なクラスがあります.(MessageQueue)
(Looper)
Handler
3.2 HandlerワークフローHandler
の使用手順に従ってHandler.sendMessage()
使用方法はメッセージキューにメッセージを送信する方法によって異なり、使用Handler.post()
、使用ActivityThread
手順の使用
/**
*
*/
// 1: Handler
private Handler mhandler = new Handler(){
// handlerMessage() UI
@Override
public void handleMessage(Message msg) {
...// UI
}
};
// 2:
Message msg = Message.obtain(); //
msg.what = 1; //
msg.obj = "AA"; //
// 3: Handler
// AsyncTask、 Thread 、 Runnable
mHandler.sendMessage(msg);
// 4: ( Handler)
// AsyncTask、 Thread 、 Runnable
/**
*
*/
private Handler mhandler = new Handler(){
// handlerMessage() UI
@Override
public void handleMessage(Message msg) {
...// UI
}
};
/**
* :Handler
* : Handler &
* :
* a. Handler ; ,Handler
* b. = Looper , Looper ( Looper )
* c. : Handler Looper = Looper
*/
public Handler() {
this(null, false);
// ->> 1
}
/**
* 1:this(null, false) = Handler(null,false)
*/
public Handler(Callback callback, boolean async) {
...//
// 1. Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// Looper.myLooper() : Looper ; Looper
// : Looper , Handler
// Handler , Looper
// : Loop.getMainLooper() Looper
// 2. (MessageQueue)
mQueue = mLooper.mQueue;
// Looper (MessageQueue)
// , handler Looper MessageQueue
}
上記の使用手順では、Looperオブジェクト&対応するメッセージキューオブジェクト(MessageQueue)を作成する手順はありません.
手順1までの暗黙的な操作1:ループオブジェクト(Looper)&メッセージキューオブジェクト(MessageQueue)の作成
/**
* 1:Looper.prepare()
* : ( ) 1 (Looper), 1 (MessageQueue)
* :
*/
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 1. sThreadLocal null,
// Looper.prepare() = 1 1 Looper
// :sThreadLocal = 1 ThreadLocal ,
sThreadLocal.set(new Looper(true));
// 2. Looper.prepare(), Looper & ThreadLocal
// :Looper Thread
// Looper ->> a
}
/**
* a:Looper
**/
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
// 1. 1 (MessageQueue)
// 1 Looper , (MessageQueue)
mRun = true;
mThread = Thread.currentThread();
}
/**
* 2:Looper.prepareMainLooper()
* : (UI ) 1 (Looper), 1 (MessageQueue)
* : (UI ) , Looper ,
*/
// Android , 1 (ActivityThread, UI )
// , ActivityThread 1 main() =
// main() Looper.prepareMainLooper() 1 Looper
/**
* :main()
**/
public static void main(String[] args) {
... //
Looper.prepareMainLooper();
// 1. 1 Looper , 1 (MessageQueue)
// Looper.prepare()
// :prepare(): 1 Looper
ActivityThread thread = new ActivityThread();
// 2.
Looper.loop();
// 3. ->>
}
まとめ:
main()
の静的main()
が自動的に呼び出されます.一方、Looper.prepareMainLooper()
内ではLooper
メインスレッドを呼び出して1つのMessageQueue
オブジェクトを生成するとともに、対応するLooper
オブジェクトも生成する1.すなわち、メインスレッドの
Looper.prepare()
オブジェクトは自動的に生成され、手動で生成する必要はない.一方、サブスレッドのLooperオブジェクトは、Looper
で手動で作成する必要がある.サブスレッドでLooper
オブジェクトを手動で作成しないとHandlerオブジェクトは生成されませんMessageQueue
&Looper.loop()
オブジェクトは、自動的にメッセージループに入ります.
は、別の暗黙的な操作です.ステップ1の前の暗黙的な操作2:メッセージループここでは主にLooperクラスにおけるloop()メソッド
/**
- : Looper.loop()
- : , 、 Handler
- :
- a. ,
-
b. : MessageQueue quit()
*/
public static void loop() {
...//
// 1. Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// myLooper() : sThreadLocal Looper ; me null
// loop() prepare(), 1 Looper
final MessageQueue queue = me.mQueue;
// Looper (MessageQueue)
// 2. ( for )
for (;;) {
// 2.1
Message msg = queue.next();
if (msg == null) {
return;
}
// next():
// ,
// ->> 1
// 2.2 Handler
msg.target.dispatchMessage(msg);
// Message msg target
// target 1 handler
// ->> 2
// 3.
msg.recycle();
}
}
/**
- 1:queue.next()
- : (MessageQueue)
-
: ,
*/
Message next() {
...//
//
// or
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// nativePollOnce native , nextPollTimeoutMillis -1,
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// , : Message
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
//
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// , nextPollTimeoutMillis -1
// ,
nextPollTimeoutMillis = -1;
}
......
}
.....
}
}//
/**
- 2:dispatchMessage(msg)
- : (Handler)
-
: Handler & msg
*/
public void dispatchMessage(Message msg) {
// 1. msg.callback , post(Runnable r)
// handleCallback(msg), Runnable run()
// “post(Runnable r)”
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 2. msg.callback , sendMessage(Message msg) ( )
// handleMessage(msg), handleMessage(msg) ->> 3
handleMessage(msg);
}
}
/**
- 3:handleMessage(msg)
-
: = , Handler =
**/
public void handleMessage(Message msg) {
... // Handler
}
### :
-
= + Handler
-
Handler : dispatchMessage(msg)
handleMessage(Message msg)
を して し、 には き みのmsg.callback
をコールバックしてメッセージ の
を する- に :メッセージ
(dispatchMessage(msg))
、1 の の が われます.post(Runnable r)
が でなければ、Runnable
を してメッセージを したことを し、 コールバックrun()
に されたmsg.callback
が であれば、sendMessage(Message msg)
を してメッセージを したことを す.
2:メッセージ・オブジェクトの /**
*
*/
Message msg = Message.obtain(); //
msg.what = 1; //
msg.obj = "AA"; //
/**
* :Message.obtain()
* :
* : Message new Message.obtain()
*/
public static Message obtain() {
// Message 1 Message , Message
// obtain()
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
// : obtain()” “ , new
}
// , new
return new Message();
}
### 3:
マルチスレッドの :handleMessage(msg)
, Threadクラス, AsyncTask
/**
*
*/
mHandler.sendMessage(msg);
/**
* :mHandler.sendMessage(msg)
* : (Handler)
* : (Message ->> MessageQueue)
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
// ->> 1
}
/**
* 1:sendMessageDelayed(msg, 0)
**/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
// ->> 2
}
/**
* 2:sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)
**/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
// 1. (MessageQueue)
MessageQueue queue = mQueue;
// 2. enqueueMessage ->> 3
return enqueueMessage(queue, msg, uptimeMillis);
}
/**
* 3:enqueueMessage(queue, msg, uptimeMillis)
**/
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 1. msg.target this
// : Handler msg target
msg.target = this;
// Looper loop() , msg, msg.target.dispatchMessage(msg)
// Handler
// 2. enqueueMessage()
// :Handler , ->> 4
return queue.enqueueMessage(msg, uptimeMillis);
}
/**
* 4:queue.enqueueMessage(msg, uptimeMillis)
* : (MessageQueue)
* : , (Message ->> MessageQueue)
* : 、
*/
boolean enqueueMessage(Message msg, long when) {
...//
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//
// a. , & ,
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
// b. , (Message)
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
// , Looper
// Handler & Handler
// Handler.handleMessage()
(より くの なプロジェクトがダウンロードされています. は きます.ソースコード. の はgithubをアップロードします.)Runnable