一直对handler似懂非懂,此次看了别的文章加上本身的理解,终于明白Handler究竟是如何实现线程间的通讯了.你们共同探讨研究.
首先得明白,一个线程只有一个Looper和MessageQueue.调用本线程的Handler只能发送Message到本线程的MessageQueue.那怎么区分Handler是哪一个线程的呢,是经过Handler对象中的Looper对象.而后本线程Looper对象loop(),不断从MessageQueue取消息.bash
//内存泄漏的问题请先忽略
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
...
}
}
};
复制代码
直接新建一个Handler,它是主线程的.答案在源码.看下面.ide
//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中已经初始化过了,这里很少说.oop
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()中就能够收到子线程发来的Messageui
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);
...
}
}
复制代码
D/ScrollingActivity: handleMessage: 接收到来自mess_thread1的消息
D/ScrollingActivity: handleMessage: msg.obj=我是子线程1发来的消息
复制代码
这里有个问题,当我在主线程使用子线程Handler时,子线程的Handler没有初始化好怎么办?咱们这样解决:
首先: 子线程里初始化Handler
再次: 子线程发送给主线程消息: 子线程的Handler准备好了
再次: 主线程使用子线程的Handler发送消息
最后: 子线程接收并处理主线程发送过来的消息spa
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){
...
}
}
}
复制代码
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();
}
复制代码
//接收处理子线程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;
}
}
};
复制代码
//使用子线程handler发送消息到子线程
private void sendMessageToChildThread() {
Message message = childThreadHandler.obtainMessage();
message.what = mess_mainThread;
message.obj = "我是主线程,已收到子线程handler准备好的消息";
childThreadHandler.sendMessage(message);
}
复制代码
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;
...
}
}
}
复制代码
handleMessage: child_handler_ok
handleMessage: msg.obj=子线程handler准备好了
handleMessage: mess_mainThread
handleMessage: msg.obj=我是主线程,已收到子线程handler准备好的消息
复制代码
//在子线程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();
}
复制代码
//这里说明一下,因为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;
}
}
}
复制代码
D/ScrollingActivity: handleMessage: child2_thread
D/ScrollingActivity: handleMessage: msg.obj=我是另外一个子线程发送的消息
复制代码
想给哪一个线程发消息,就使用目标线程的Handler对象调用sendMessage(message).
而区别Handler是哪一个线程的,就是Handler持有哪一个线程的Looper.线程