Handler的定义
handler 是为了实现 异步而生的
Android是消息启动的,UI线程是一个Looper线程 , Looper中维护这一个MessageQueue , UI线程将不断处理这些消息 以完成UI的更新等异步操作
handler扮演了往已经Looper线程的message queue上添加消息和处理消息的角色(只处理由自己发出的消息),即 通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。
案例解析:
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 但是如果此时需要一个耗时的操作,例如: 联网读取数据, 如果你放在主线程中的话,界面会出现假死现象, 因为在处理你的耗时操作 如果这个操作超过5s就会anr
所以耗时操作应该放在一个子线程中, 但这样子线程就会涉及到UI更新,Android主线程是线程不安全的,(更新UI只能在主线程中更新,子线程中不能更新UI)
那么子线程就需要通知主线程来更新数据,于是 就可以使用Handler. 如果Handler对象在主线程中被创建,那这个Handler就运行在主线程中(UI线程中), 在子线程中可以 用这个handler发送消息 然后这个handler就把这个消息放到主线程的mq中 然后UI线程就能可以 进行更新等操作了:
具体如下图:
Handler实现原理
分两个方面来讲
1.发送消息:
通过handler发出的message有如下特点:
1.message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码
msg.target.dispatchMessage(msg);
2.post发出的message,其callback为Runnable对象
Handler的使用
1.最基本的使用 以获取sina的html为例
首先是让Thread发送消息:
然后让handler处理这个消息
2.更多使用
一个小实例: 使用handler实现 实现在ui线程不断做某些事情例如轮播广告 注意不要做非常耗时的操作 会阻塞UI线程的
参考文献
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
handler 是为了实现 异步而生的
Android是消息启动的,UI线程是一个Looper线程 , Looper中维护这一个MessageQueue , UI线程将不断处理这些消息 以完成UI的更新等异步操作
handler扮演了往已经Looper线程的message queue上添加消息和处理消息的角色(只处理由自己发出的消息),即 通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。
案例解析:
当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 但是如果此时需要一个耗时的操作,例如: 联网读取数据, 如果你放在主线程中的话,界面会出现假死现象, 因为在处理你的耗时操作 如果这个操作超过5s就会anr
所以耗时操作应该放在一个子线程中, 但这样子线程就会涉及到UI更新,Android主线程是线程不安全的,(更新UI只能在主线程中更新,子线程中不能更新UI)
那么子线程就需要通知主线程来更新数据,于是 就可以使用Handler. 如果Handler对象在主线程中被创建,那这个Handler就运行在主线程中(UI线程中), 在子线程中可以 用这个handler发送消息 然后这个handler就把这个消息放到主线程的mq中 然后UI线程就能可以 进行更新等操作了:
具体如下图:

Handler实现原理
分两个方面来讲
1.发送消息:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// 此方法用于向对应的Looper的MQ上发送Runnable对象,它的run方法将在handler对应的Looper线程中执行
public
final
boolean
post(Runnable r)
{
return
sendMessageDelayed(getPostMessage(r),
0
);
// getPostMessage(r)将runnable封装成message
}
private
final
Message getPostMessage(Runnable r) {
Message m = Message.obtain();
//message工厂
m.callback = r;
//将runnable设为message的callback,
return
m;
}
public
boolean
sendMessageAtTime(Message msg,
long
uptimeMillis)
{
boolean
sent =
false
;
MessageQueue queue = mQueue;
if
(queue !=
null
) {
msg.target =
this
;
// message的target必须设为该handler
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else
{
RuntimeException e =
new
RuntimeException(
this
+
" sendMessageAtTime() called with no mQueue"
);
Log.w(
"Looper"
, e.getMessage(), e);
}
return
sent;
}
|
通过handler发出的message有如下特点:
1.message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码
msg.target.dispatchMessage(msg);
2.post发出的message,其callback为Runnable对象
Handler处理消息
消息的处理是通过核心方法dispatchMessage(Message msg)与handleMessage(Message msg)完成的
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
View Code
// 处理消息,该方法由looper调用
public
void
dispatchMessage(Message msg) {
if
(msg.callback !=
null
) {
// 如果message设置了callback,即runnable消息,处理callback
handleCallback(msg);
}
else
{
// 如果handler本身设置了callback,则执行callback
if
(mCallback !=
null
) {
/* 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。
if
(mCallback.handleMessage(msg)) {
return
;
}
}
// 如果message没有callback,则调用handler的钩子方法handleMessage
handleMessage(msg);
}
}
// 处理runnable消息
private
final
void
handleCallback(Message message) {
message.callback.run();
//直接调用run方法!
}
// 由子类实现的钩子方法
public
void
handleMessage(Message msg) {
}
|
方法由开发者实现外(实现具体逻辑),handler的内部工作机制对开发者是透明的。这正是handler API设计的精妙之处
Handler的使用
1.最基本的使用 以获取sina的html为例
首先是让Thread发送消息:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
new
Thread() {
public
void
run() {
Message msg = myHandler.obtainMessage();
try
{
html = HttpUtil.fromHtml(HttpUtil
.getHtml(
"http://wap.sina.com"
));
msg.what =
0
;
}
catch
(Exception e) {
e.printStackTrace();
msg.what =
1
;
}
myHandler.sendMessage(msg);
}
}.start();
|
然后让handler处理这个消息
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
Handler myHandler =
new
Handler() {
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
0
:
textView1.setText(html);
progressDialog.dismiss();
break
;
case
1
:
textView1.setText(
"当前无数据"
);
progressDialog.dismiss();
break
;
}
super
.handleMessage(msg);
}
};
|
2.更多使用
Handler中分发消息的一些主要方法的说明
post(Runnable) //执行某个动作 也就是 排列一个Runnable对象到主线程队列中,
postAtTime(Runnable,long) 在指定时间(linux时间戳) 执行这个动作
postDelayed(Runnable long) 延时多少时间执行这个动作
sendEmptyMessage(int) 发送int消息 sendMessage允许你发送一个带数据的Message对象到handler对应线程的消息队列中
sendMessage(Message) 发送消息 这个message中可以包含两个int和一个object对象 注意 开销比上面要大
sendMessageAtTime(Message,long) 在指定时间发送消息
sendMessageDelayed(Message,long) //延时多少时间后发送这个消息
一个小实例: 使用handler实现 实现在ui线程不断做某些事情例如轮播广告 注意不要做非常耗时的操作 会阻塞UI线程的
01
02
03
04
05
06
07
08
09
10
11
|
private
Runnable runnable =
new
Runnable() {
@Override
public
void
run() {
if
(!isPlay)
return
;
handler.postDelayed(
this
,
1000
);
//TODO do sth
}
};
runnable.run();
|
参考文献
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
http://blog.youkuaiyun.com/luoshengyang/article/details/6817933