Android消息机制、handler运行机制

235 阅读12分钟
一、android消息机制的概述
android的消息机制主要值Handler的消息运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。MessageQueue为消息队列,它内部存储了一组消息,以队列的形式对外提供插入和删除工作,它只提供存储功能,不处理消息;而Looper会以无限循环的形式去查找是否有新的消息,如果有就处理,没有就一直等待着,还有就是looper它运行在handler创建的线程中。
二、ThreadLocal介绍
为什么要介绍它了,因为我们获取looper的时候跟它有关。
介绍:ThreadLocal是一个线程内部的数据存储类,通过它可以获取在指定的线程中的存储数据,数据存储以后,只有在指定线程中可以获取到数据,也就是说在当前线程中存储的数据只有在当前线程中才能获取,其它线程无法获取到,文字不太好理解,举个例子吧:


先定义一个ThreadLocal对象,这里选择Boolean类型的

在代码中主线程设置为ture,在#1中设置值为false,在#2中不设置值,运行结果如下:



从上面日志中可以看出,虽然在不同线程中访问同一个ThreadLocal对象,但是他们通过ThreadLocal获取的值却是不一样的,每个线程的值都是单独的 :主线程设置为true,获取的值就为true,#1设置为false,获取的值就为false;#2中没有设置值,所以获取的值为null.
三、MessageQueue工作原理
MessageQueue主要包含两个操作:插入和读取,读取操作本身会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage()和next()这俩个方法,enqueueMessage的源码如下:


这里主要就是框起来这里的赋值操作,在next()方法的时候会去判断mMessage这个全局变量是否为空,而mMessage它就是我们传进来的消息对象。
在看next()方法的源码:

next()方法是个无限循环的方法,如果消息队列中没有消息就堵塞,当有新消息来时会返回这条消息,并把这条消息制为空,也就是在消息队列中移除。
四、Looper的工作原理
Looper主要的功能是,它会不停地从MessageQueue中查看是否有新的消息,如果有新的消息就会立即处理,否则就一直堵塞在那里。先看它的构造方法:

在构造方法中,它会建立一个MessageQueue消息队列,然后把当前线程对象保存起来。
我们知道Handler工作需要Looper,如果没有会报错,我们也知道可以通过Looper.prepare()来为当前线程创建一个Looper,源码如下:

代码很简单,给ThreadLocal设置一个Looper();

创建Looper后可以通过Looper.loop()来开启消息循环,如下图:


Looper最重要的一个方法就Loop()方法,只有调用了Loop()方法以后,消息循环才正真的起作用,接下来详细的讲解一下,它的源码如下:

loop这个方法主要去循环消息队列中的消息,如果有的话就调用handler的dispatchMessage()方法。
下面来介绍loop几个主要的方法:
1.myLooper(),首先看源码:


这个很简单,就是获取我们初始化时设置进去的looper,只要记住它获取的是handler创建线程的Looper就行了。
获取Looper后就可以得到messageQueue了,因为我们初始化looper的时候就创建了一个,可以去看looper构造方法的代码就明白了。
获取messageQueue后就调用它的next()方法,前面有讲到它的源码它就是,如果有新的消息就返回,并把消息移除,如果没有消息就堵塞。
然后判断msg是否为空,如果为空的话就跳出循环,可以调用messageQueue的quit()方法让looper跳出循环:

msg.target.dispatchMessage(msg)这个方法是非常重要,它让消息从线程中进行了切换,因为msg.target其实就是一个handler:

当我们调用Handler的obtainMesage()方法时,它会调用message的obtain方法,并把自己传进去:

然后在message类中设置target的值:

所以从上面代码中看出,msg.target就是我们创建的handler,然后获取的looper也是跟handler运行在同一线程,所以他调用的就是我们创建的handler的dispatchMessage()方法:




从这个方法可以看出他判断了msg是否有回调方法,然后handler自己是否有设置回调方法,如果没有的话就调用handleMessage()方法。
五、Handler的工作原理
handler主要介绍一个enqueueMessage()方法,因为所有的发送消息的方法调用的都是这个方法:

从代码中发现它最后还是调用了messageQueue中的enqueueMessage()方法,而这个方法就是往消息队列中添加一条数据。
然后看一下handler的构造方法:



handler有七个构造方法,他们分别调用了这两个构造方法,一个是不传Looper一个是传递looper。

六、主线程的Looper创建
android的主线程就是ActivityThread,主线程的入口方法为main(),源码如下:

可以看到在主线程中系统会通过Looper.prepareMainLooper()方法创建Looper,并通过Looper.loop()来开始循环,所以在主线程中不用我们自己初始化Looper;
prepareMainLooper()源码:

----------------------------------------------------------------------------------------------------------------------------
下面我自己写了个handler消息机制的代码,只写了一下重要的代码,有很多的细节和判断没有涉及到,但是整个流程是没有问题的,还有因为是死循环可能会有点卡:
1.创建handler类:
  1. public class Handler {  
  2.   
  3. private MessageQueue queue;  
  4.   
  5. public void handleMessage(Message msg) {  
  6.   
  7. }  
  8.   
  9. public void dispatchMessage(Message msg) {  
  10. //调用handleMessage  
  11. handleMessage(msg);  
  12. }  
  13.   
  14. public final Message obtainMessage()  
  15. {  
  16. return Message.obtain(this);  
  17. }  
  18.   
  19. public Handler(){  
  20. //在主线程会自动获取looper  
  21. Looper looper = Looper.myLooper();  
  22. queue = looper.queue;  
  23.   
  24. }  
  25.   
  26. public Handler(Looper looper){  
  27. queue = looper.queue;  
  28.   
  29. }  
  30.   
  31. public boolean sendMessage(Message msg){  
  32.   
  33. return queue.enQuequMessage(msg,0);  
  34.   
  35. }  
  36. }  
public class Handler {

private MessageQueue queue;

public void handleMessage(Message msg) {

}

public void dispatchMessage(Message msg) {
//调用handleMessage
handleMessage(msg);
}

public final Message obtainMessage()
{
return Message.obtain(this);
}

public Handler(){
//在主线程会自动获取looper
Looper looper = Looper.myLooper();
queue = looper.queue;

}

public Handler(Looper looper){
queue = looper.queue;

}

public boolean sendMessage(Message msg){

return queue.enQuequMessage(msg,0);

}
}



2.创建Message类:

  1. public class Message {  
  2.   
  3. public Handler target;  
  4. public Object obj;  
  5. public int what;  
  6. public int arg1;  
  7. public Message next;  
  8. public int flags;  
  9. private static Message sPool;  
  10.   
  11.   
  12. public static Message obtain(){  
  13. if (sPool != null){  
  14.   
  15. Message m = sPool;  
  16. sPool = m.next;  
  17. m.next = null;  
  18. m.flags = 0// clear in-use flag  
  19. return m;  
  20. }  
  21.   
  22. return new Message();  
  23.   
  24. }  
  25.   
  26. public static Message obtain(Handler h) {  
  27. Message m = obtain();  
  28. m.target = h;//在这里赋值handler  
  29.   
  30. return m;  
  31. }  
  32.   
  33. }  
public class Message {

public Handler target;
public Object obj;
public int what;
public int arg1;
public Message next;
public int flags;
private static Message sPool;


public static Message obtain(){
if (sPool != null){

Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
return m;
}

return new Message();

}

public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;//在这里赋值handler

return m;
}

}


3.创建MessageQueue类
  1. public class MessageQueue {  
  2.   
  3. private Message mMessage;  
  4. private boolean mQuitting;  
  5.   
  6.   
  7. public boolean enQuequMessage(Message msg,long when){  
  8.   
  9. if (msg.target == null){  
  10. //判断handler是否为空  
  11. throw new IllegalArgumentException("Message must have a target.");  
  12. }  
  13.   
  14. Message p = mMessage;  
  15. if (p == null){  
  16. msg.next = p ;//这里设置为null  
  17. mMessage = msg;//把消息赋值给成员变量  
  18. }  
  19.   
  20. return true;  
  21.   
  22. }  
  23.   
  24. public Message next(){  
  25. for (;;){  
  26. Message prevMsg = null;  
  27. Message msg = mMessage;  
  28. if (msg != null && msg.target == null){  
  29. //判断handler等于null  
  30. do {  
  31. prevMsg = msg;  
  32. msg = msg.next;//这里把他设置成了null,因为上面设置了值为null  
  33. }while (msg != null);  
  34. }  
  35. if (msg != null){  
  36. if (prevMsg != null) {  
  37. //把next设置成null  
  38. prevMsg.next = msg.next;  
  39. else {  
  40. mMessage = msg.next;//把成员变量mMessage设置成null  
  41. }  
  42. msg.next = null;  
  43. return msg;  
  44. }  
  45.   
  46. if (mQuitting){  
  47. return null;  
  48.   }  
  49.   
  50.  }  
  51.   
  52. }  
  53.   
  54. /** 
  55. * 退出循环 
  56. * @param mQuitting 
  57. */  
  58. public void quit(boolean mQuitting){  
  59. this.mQuitting = mQuitting;  
  60.   
  61.    }  
  62.   
  63. }  
public class MessageQueue {

private Message mMessage;
private boolean mQuitting;


public boolean enQuequMessage(Message msg,long when){

if (msg.target == null){
//判断handler是否为空
throw new IllegalArgumentException("Message must have a target.");
}

Message p = mMessage;
if (p == null){
msg.next = p ;//这里设置为null
mMessage = msg;//把消息赋值给成员变量
}

return true;

}

public Message next(){
for (;;){
Message prevMsg = null;
Message msg = mMessage;
if (msg != null && msg.target == null){
//判断handler等于null
do {
prevMsg = msg;
msg = msg.next;//这里把他设置成了null,因为上面设置了值为null
}while (msg != null);
}
if (msg != null){
if (prevMsg != null) {
//把next设置成null
prevMsg.next = msg.next;
} else {
mMessage = msg.next;//把成员变量mMessage设置成null
}
msg.next = null;
return msg;
}

if (mQuitting){
return null;
  }

 }

}

/**
* 退出循环
* @param mQuitting
*/
public void quit(boolean mQuitting){
this.mQuitting = mQuitting;

   }

}


4.创建Looper类
  1. public class Looper {  
  2.   
  3.   
  4. private static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();  
  5.   
  6.   
  7. public MessageQueue queue;  
  8. // private Thread thread;  
  9.   
  10. public Looper(boolean quitAllowed){  
  11. queue = new MessageQueue();  
  12. // thread = new Thread();  
  13. }  
  14. public static void prepare() {  
  15. prepare(true);  
  16. }  
  17.   
  18. private static void prepare(boolean quitAllowed) {  
  19. if (sThreadLocal.get() != null) {  
  20. //判断是否已经有了looper  
  21. throw new RuntimeException("Only one Looper may be created per thread");  
  22. }  
  23. sThreadLocal.set(new Looper(quitAllowed));  
  24. }  
  25.   
  26. /** 
  27. * 从ThreadLocal中获取looper 
  28. * @return 
  29. */  
  30. public static @Nullable Looper myLooper() {  
  31. return sThreadLocal.get();  
  32.  }  
  33.   
  34.   
  35. public static void loop(){  
  36.   
  37. Looper me = myLooper();//获取looper,这个looper跟handler在同一个线程  
  38. if (me == null) {  
  39. //判断是否为空  
  40. throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  41.   }  
  42.   
  43. MessageQueue queue = me.queue;  
  44. for (;;){  
  45. //进入死循环  
  46. Message msg = queue.next();//掉用next方法,如果没有消息的话会一直堵塞在这里  
  47.   
  48. if (msg == null){  
  49. //当next()方法返回null的时候跳出循环  
  50. return;  
  51.   }  
  52. if (msg != null){  
  53. //调用handler的方法 主要的线程切换就在这里完成 因为这里looper是handler运行线程的looper  
  54. msg.target.dispatchMessage(msg);  
  55.    }  
  56.   
  57.   }  
  58.   
  59. }  
  60.   
  61. public static Looper getMainLooper() {  
  62. prepare();  
  63. return myLooper();  
  64.   }  
  65.   
  66. }  
public class Looper {


private static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();


public MessageQueue queue;
// private Thread thread;

public Looper(boolean quitAllowed){
queue = new MessageQueue();
// thread = new Thread();
}
public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
//判断是否已经有了looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}

/**
* 从ThreadLocal中获取looper
* @return
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
 }


public static void loop(){

Looper me = myLooper();//获取looper,这个looper跟handler在同一个线程
if (me == null) {
//判断是否为空
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
  }

MessageQueue queue = me.queue;
for (;;){
//进入死循环
Message msg = queue.next();//掉用next方法,如果没有消息的话会一直堵塞在这里

if (msg == null){
//当next()方法返回null的时候跳出循环
return;
  }
if (msg != null){
//调用handler的方法 主要的线程切换就在这里完成 因为这里looper是handler运行线程的looper
msg.target.dispatchMessage(msg);
   }

  }

}

public static Looper getMainLooper() {
prepare();
return myLooper();
  }

}


5.创建mainActivity测试


运行结果:


根据日志可以看出运行在不同的线程中,接收数据没有问题。

以下是我自己的总结出来的handler的运行流程:
  1. 1.looper.perpp();初始化Looper和消息队列 MessageQueue(在主线程中不需要手动操作)  
  2. 2.Handler handler = new Handler();创建handler,获取looper, 获取消息队列MessageQueue的值 mLooper.mqueue  
  3. 3.Message msg = handler.obtainMessage();获取消息对象,并把handler跟Message对象的target进行绑定  
  4. 4.msg.obj = xxx;设置传递消息的值  
  5. 5.调用handler.sendMessage(msg)方法  
  6. 6.调用消息队列MessageQueue方法的enqueueMessage()方法添加消息到消息队列  
  7. 7.调用looper.loop()方法(在主线中不需要手动操作)  
  8. 8.loop方法里先获取looper  
  9. 9.然后获取消息队列MessageQueue  
  10. 10.然后调用消息队列的next()方法开始循环消息  
  11. 11.如果有消息的话调用handler.dispatchMessage()方法  
  12. 12.在dispatchMessage()方法中判断是否消息的回调和handler的回调方法如果没有就调用handleMessage()方法;  
1.looper.perpp();初始化Looper和消息队列 MessageQueue(在主线程中不需要手动操作)
2.Handler handler = new Handler();创建handler,获取looper, 获取消息队列MessageQueue的值 mLooper.mqueue
3.Message msg = handler.obtainMessage();获取消息对象,并把handler跟Message对象的target进行绑定
4.msg.obj = xxx;设置传递消息的值
5.调用handler.sendMessage(msg)方法
6.调用消息队列MessageQueue方法的enqueueMessage()方法添加消息到消息队列
7.调用looper.loop()方法(在主线中不需要手动操作)
8.loop方法里先获取looper
9.然后获取消息队列MessageQueue
10.然后调用消息队列的next()方法开始循环消息
11.如果有消息的话调用handler.dispatchMessage()方法
12.在dispatchMessage()方法中判断是否消息的回调和handler的回调方法如果没有就调用handleMessage()方法;