Android处理程序:Handler Looper Message源码研究

线程Thread的线程变量ThreadLocal中,存放着这个线程的looper;Looper在初始化时,会新建一个消息队列messageQueue,之后Looper进入一个死循环,等待从消息队列MessageQueue取得消息Message(Looper是消费者),没有消息时会阻塞;

我们程序中的handler,会通过sendMessage或post方法,往MessageQueue中添加消息时,添加的这个Message,会记录他是属于哪个Handler发出的,同时根据message.when,决定新添加的这个Message在Queue中的位置,MessageQueue中只有一个当前的Message,队列关系是通过Message中的prev,next维护的,Message是一个链表的节点;

添加消息后,消费者Looper取得Message,并调用建立Message的Hander的dispatchMessage方法。

咋一看好像Handler即sendMessage,又handlerMessage,事情还是只有一个线程在做事情。

但是后来想想,明白了这样设计的必要性。

因为这个***的线程一般而言,都是mainUI线程,如果你有个可以分成多个小任务的任务要处理,你没有使用Handler,直接执行,也许系统忙于处理你这个任务,而无法及时响应用户事件,从而导致ANR的抛出。

如果你把你的任务拆成几个小任务,用Handler来实现,那么系统就可以把你的小任务推到后面来处理,抽出时间来响应用户操作。

如果真的有大任务,一般式需要另外线程去处理,或者开启Service。

一个在新线程中使用handler例子,我们来分析下源码

Java代码

 
 
 
  1. new Thread(new Runnable() { 
  2. @Override public void run() { 
  3. Handler handler; 
  4. //1、初始化Looper 
  5. Looper.prepare(); 
  6. //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法 
  7. handler= new Handler() { 
  8. @Override public void handleMessage(Message msg) { 
  9. }; 
  10. // 3、发送消息 
  11. handler.sendMessage(new Message()); 
  12. handler.post(new Runnable()) 
  13. handler.obtainMessage(1, "hello").sendToTarget(); 
  14. //4、启动消息循环 
  15. Looper.loop(); 
  16. }).start(); 

1 Java代码

 
 
 
  1. public static final void prepare() { 
  2. if (sThreadLocal.get() != null) { // 每个线程,只能有一个Looper对象 
  3. throw new RuntimeException("Only one Looper may be created per thread"); 
  4. // 如果当前线程没有Looper,新建一个,构造函数是private的 
  5. sThreadLocal.set(new Looper()); 
  6. private Looper() { 
  7. mQueue = new MessageQueue(); // 建立消息队列 
  8. mRun = true; 
  9. mThread = Thread.currentThread(); 

2 Java代码

 
 
 
  1. public Handler(){ 
  2. mLooper = Looper.myLooper(); // 取得当前线程的Looper,如果抛异常 
  3. if (mLooper == null) { 
  4. throw new RuntimeException( 
  5. "Can't create handler inside thread that has not called Looper.prepare()"); 
  6. mQueue = mLooper.mQueue; // 取得消息队列 
  7. mCallback = null; 

3 Java代码

 
 
 
  1. //不管调用哪个方法,最终执行的是 
  2. public boolean sendMessageAtTime(Message msg, long uptimeMillis){ 
  3. boolean sent = false; 
  4. // 取得消息队列 
  5. MessageQueue queue = mQueue; 
  6. if (queue != null) { 
  7. msg.target = this; // 消息发出着是自己 
  8. sent = queue.enqueueMessage(msg, uptimeMillis); // 添加到消息队列中 
  9. else { 
  10. RuntimeException e = new RuntimeException( 
  11. this + " sendMessageAtTime() called with no mQueue"); 
  12. Log.w("Looper", e.getMessage(), e); 
  13. return sent; 
  14. final boolean enqueueMessage(Message msg, long when) { 
  15. if (msg.when != 0) { 
  16. throw new AndroidRuntimeException(msg 
  17. + " This message is already in use."); 
  18. if (msg.target == null && !mQuitAllowed) { 
  19. throw new RuntimeException("Main thread not allowed to quit"); 
  20. synchronized (this) { 
  21. if (mQuiting) { 
  22. RuntimeException e = new RuntimeException( 
  23. msg.target + " sending message to a Handler on a dead thread"); 
  24. Log.w("MessageQueue", e.getMessage(), e); 
  25. return false; 
  26. } else if (msg.target == null) { 
  27. mQuiting = true; 
  28. msg.when = when; 
  29. Message p = mMessages; 
  30. // 之前没有其他消息了,MessageQueue中当前消息mMessages 就是传递进来的msg 
  31. if (p == null || when == 0 || when < p.when) {  
  32. msg.next = p; 
  33. mMessages = msg; 
  34. this.notify(); // 唤醒  
  35. } else {  
  36. // 之前有其他消息了,将传递的msg放到适合的位置,根据when  
  37. Message prev = null;  
  38. while (p != null && p.when <= when) {  
  39. prev = p;  
  40. p = p.next;  
  41. }  
  42. msg.next = prev.next;  
  43. prev.next = msg;  
  44. this.notify(); // 唤醒  
  45. }  
  46. }  
  47. return true;  

4 Java代码

 
 
 
  1. public static final void loop() { 
  2. Looper me = myLooper(); 
  3. MessageQueue queue = me.mQueue; 
  4. while (true) { // 死循环 
  5. Message msg = queue.next(); // 当队列中没有消息时会阻塞 
  6. if (msg != null) { 
  7. if (msg.target == null) { // 消息没有发送者时,退出消息循环 
  8. // No target is a magic identifier for the quit message. 
  9. return; 
  10. if (me.mLogging!= null) me.mLogging.println( 
  11. ">>>>> Dispatching to " + msg.target + " " 
  12. + msg.callback + ": " + msg.what 
  13. ); 
  14. // 调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler 
  15. msg.target.dispatchMessage(msg); 
  16. if (me.mLogging!= null) me.mLogging.println( 
  17. "<<<<< Finished to " + msg.target + " " 
  18. + msg.callback); 
  19. msg.recycle(); 
  20. final Message next() { 
  21. boolean tryIdle = true; 
  22. while (true) { 
  23. synchronized (this) { 
  24. // 没有消息的或,会阻塞 
  25. try { 
  26. if (mMessages != null) { 
  27. if (mMessages.when-now > 0) { 
  28. Binder.flushPendingCommands(); 
  29. this.wait(mMessages.when-now); 
  30. } else { 
  31. Binder.flushPendingCommands(); 
  32. this.wait(); 
  33. catch (InterruptedException e) { 

总结

Handler作用:

1. 执行计划任务

2. 线程间通信

一个handler,只能接收到自己发出的message。handler实例与消息Message处理是关联的,发送和接受要匹配

Handler操作队列,主要是在子线程操作主线程的消息队列

Handler是实现异步的一种方式,用法是在主线程中建立Handler,(主线程中的Handler不用掉Looper.prepare);

在子线程(耗时操作)任务完成后sendMessage,这个Message会发送到主线程的消息队列中,主线程Handler的重写dispatchMessage方法,做新线程任务完成后的事情,大部分是更新UI。

本文题目:Android处理程序:Handler Looper Message源码研究
浏览路径:http://www.shufengxianlan.com/qtweb/news48/393648.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联