一直对handler似懂非懂,这次看了别的文章加上自己的理解,终于明白Handler到底是如何实现线程间的通信了.大家共同探讨研究.
首先得明白,一个线程只有一个Looper和MessageQueue.调用本线程的Handler只能发送Message到本线程的MessageQueue.那怎么区分Handler是哪个线程的呢,是通过Handler对象中的Looper对象.然后本线程Looper对象loop(),不断从MessageQueue取消息。
1.主线程初始化Handler
//内存泄漏的问题请先忽略
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
}
}
};
直接新建一个Handler,它是主线程的.答案在源码.看下面.
//Handler源码片段
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
...
mLooper = Looper.myLooper(); //注意这句
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
...
mLooper = Looper.myLooper(); 这句代码获取的是主线程的Looper,而它在ActivityThread中已经初始化过了,这里不多说.
2.子线程发消息给主线程
a.在子线程里发送消息
private void childThreadSendMessageToMain() {
new Thread(){
@Override
public void run() {
super.run();
Message message = handler.obtainMessage();
message.what = mess_thread1;
message.obj = "我是子线程1发来的消息";
handler.sendMessage(message); //注意这句
}
}.start();
}
handler.sendMessage(message); 这里的handler是我们上面在主线程初始化的,是主线程的Handler,这样在主线程的handleMessage()中就可以收到子线程发来的Message
b.在主线程接收消息
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
//注意这里
case mess_thread1:
Log.d(TAG, "handleMessage: 接收到来自mess_thread1的消息");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
...
}
}
c.结果打印
D/ScrollingActivity: handleMessage: 接收到来自mess_thread1的消息
D/ScrollingActivity: handleMessage: msg.obj=我是子线程1发来的消息
2.主线程发消息给子线程
这里有个问题,当我在主线程使用子线程Handler时,子线程的Handler没有初始化好怎么办?我们这样解决:
首先: 子线程里初始化Handler
再次: 子线程发送给主线程消息: 子线程的Handler准备好了
再次: 主线程使用子线程的Handler发送消息
最后: 子线程接收并处理主线程发送过来的消息
a.我们改变写法,在主线程写一个类继承自Handler
private class ChildHandler extends Handler{
//参数为looper,到时候传入一个子线程的looper,这个handler就成了子线程的了
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
}
}
}
b.开始在子线程new Handler,并且发送消息
private void initChildHandler(){
new Thread(){
@Override
public void run() {
Looper.prepare();
childThreadHandler = new ChildHandler(Looper.myLooper());
Message message = handler.obtainMessage();
message.what = child_handler_ok;
message.obj = "子线程handler准备好了";
handler.sendMessage(message);
Looper.loop();
}
}.start();
}
c.主线程接收"子线程handler准备好"的消息,并使用子线程的Handler给子线程发消息
//接收处理子线程handler准备好的消息
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case child_handler_ok:
Log.d(TAG, "handleMessage: 接收到子线程消息");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
sendMessageToChildThread();
break;
}
}
};
d.sendMessageToChildThread方法的具体实现
//使用子线程handler发送消息到子线程
private void sendMessageToChildThread() {
Message message = childThreadHandler.obtainMessage();
message.what = mess_mainThread;
message.obj = "我是主线程,已收到子线程handler准备好的消息";
childThreadHandler.sendMessage(message);
}
e.子线程接收主线程发来的消息
private class ChildHandler extends Handler{
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case mess_mainThread:
Log.d(TAG, "handleMessage: mess_mainThread");
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
...
break;
...
}
}
}
f.结果打印
handleMessage: child_handler_ok
handleMessage: msg.obj=子线程handler准备好了
handleMessage: mess_mainThread
handleMessage: msg.obj=我是主线程,已收到子线程handler准备好的消息
3.子线程发消息给子线程
a.接着上面,我们再新建一个线程,称之为子线程2,原来的子线程称之为子线程1,
//在子线程2中使用子线程1的handler发送消息,实现了子线程之间的通信
private void initChild2Thread() {
new Thread(){
@Override
public void run() {
Message message = childThreadHandler.obtainMessage();
message.what = child2_thread;
message.obj = "我是另一个子线程发送的消息";
childThreadHandler.sendMessage(message);
}
}.start();
}
b.我们在子线程1中接收
//这里说明一下,由于new的时候我们传入了子线程1的looper,所以这个handler属于子线程1
private class ChildHandler extends Handler{
private ChildHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
case child2_thread:
Log.d(TAG, "handleMessage: child2_thread" );
Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
break;
}
}
}
c.结果打印
D/ScrollingActivity: handleMessage: child2_thread
D/ScrollingActivity: handleMessage: msg.obj=我是另一个子线程发送的消息
4.总结
想给哪个线程发消息,就使用目标线程的Handler对象调用sendMessage(message).
而区别Handler是哪个线程的,就是Handler持有哪个线程的Looper.