(点击
上方公众号
,可快速关注)
来源:伯乐在线专栏作者 - PleaseCallMeCoder
链接:http://android.jobbole.com/84957/
点击 → 了解如何加入专栏作者
接上文
接下来我们看一下handler是如何发送消息的
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public
final
boolean
post
(
Runnable
r
)
{
return
sendMessageDelayed
(
getPostMessage
(
r
),
0
);
}
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public
final
boolean
sendMessageDelayed
(
Message
msg
,
long
delayMillis
)
{
if
(
delayMillis
0
)
{
delayMillis
=
0
;
}
return
sendMessageAtTime
(
msg
,
SystemClock
.
uptimeMillis
()
+
delayMillis
);
}
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds)
uptimeMillis
.
*
The time-base is {@link android.os.SystemClock#uptimeMillis}.
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public
boolean
sendMessageAtTime
(
Message
msg
,
long
uptimeMillis
)
{
MessageQueue
queue
=
mQueue
;
if
(
queue
==
null
)
{
RuntimeException
e
=
new
RuntimeException
(
this
+
" sendMessageAtTime() called with no mQueue"
);
Log
.
w
(
"Looper"
,
e
.
getMessage
(),
e
);
return
false
;
}
return
enqueueMessage
(
queue
,
msg
,
uptimeMillis
);
}
private
boolean
enqueueMessage
(
MessageQueue
queue
,
Message
msg
,
long
uptimeMillis
)
{
msg
.
target
=
this
;
if
(
mAsynchronous
)
{
msg
.
setAsynchronous
(
true
);
}
return
queue
.
enqueueMessage
(
msg
,
uptimeMillis
);
}
这里我们只列出了一种调用关系,其他调用关系大同小异,我们来分析一下
-
调用getPostMessage(r),把runnable对象添加到一个Message对象中。
-
sendMessageDelayed(getPostMessage(r), 0),基本没做什么操作,又继续调用sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)方法,在这个方法里拿到创建这个Handler对象的线程持有的MessageQueue。
-
调用enqueueMessage(queue, msg, uptimeMillis)方法,给msg对象的target变量赋值为当前的Handler对象,然后放入到MessageQueue。
那发送消息说完了,那我们的消息是怎样被处理的呢?
我们看到message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码。
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public
interface
Callback
{
public
boolean
handleMessage
(
Message
msg
);
}
/**
* Subclasses must implement this to receive messages.
*/
public
void
handleMessage
(
Message
msg
)
{
}
/**
* Handle system messages here.
*/
public
void
dispatchMessage
(
Message
msg
)
{
if
(
msg
.
callback
!=
null
)
{
handleCallback
(
msg
);
}
else
{
if
(
mCallback
!=
null
)
{
if
(
mCallback
.
handleMessage
(
msg
))
{
return
;
}
}
handleMessage
(
msg
);
}
}
private
static
void
handleCallback
(
Message
message
)
{
message
.
callback
.
run
();
}
我们看到这里最终又调用到了我们重写的handleMessage(Message msg)方法来做处理子线程发来的消息或者调用handleCallback(Message message)去执行我们子线程中定义并传过来的操作。
思考
为什么要有Handler机制
这个问题可以这么考虑
-
我们如何在子线程更新UI?——使用Handler机制传递消息到主线程(UI线程)
-
为什么我们不在子线程更新UI呢?——因为Android是单线程模型
-
为什么要做成单线程模型呢?——多线程并发访问UI可能会导致UI控件处于不可预期的状态。如果加锁,虽然能解决,但是缺点也很明显:1.锁机制让UI访问逻辑变得复杂;2.加锁导致效率低下。
Handler机制与命令模式
我在之前分享过Android源码中的命令模式,我们仔细分下一下不难看出Handler机制其实是一个非典型的命令模式。
Android主线程是如何管理子线程消息的
我们知道Android上一个应用的入口,应该是ActivityThread。和普通的Java类一样,入口是一个main方法。
public
static
void
main
(