`
yidongkaifa
  • 浏览: 4069228 次
文章分类
社区版块
存档分类
最新评论

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. newThread(newRunnable(){
  2. @Overridepublicvoidrun(){
  3. Handlerhandler;
  4. //1、初始化Looper
  5. Looper.prepare();
  6. //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法
  7. handler=newHandler(){
  8. @OverridepublicvoidhandleMessage(Messagemsg){
  9. }
  10. };
  11. //3、发送消息
  12. handler.sendMessage(newMessage());
  13. handler.post(newRunnable())
  14. handler.obtainMessage(1,"hello").sendToTarget();
  15. //4、启动消息循环
  16. Looper.loop();
  17. }
  18. }).start();

1Java代码

  1. publicstaticfinalvoidprepare(){
  2. if(sThreadLocal.get()!=null){//每个线程,只能有一个Looper对象
  3. thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");
  4. }
  5. //如果当前线程没有Looper,新建一个,构造函数是private的
  6. sThreadLocal.set(newLooper());
  7. }
  8. privateLooper(){
  9. mQueue=newMessageQueue();//建立消息队列
  10. mRun=true;
  11. mThread=Thread.currentThread();
  12. }

2Java代码

  1. publicHandler(){
  2. mLooper=Looper.myLooper();//取得当前线程的Looper,如果抛异常
  3. if(mLooper==null){
  4. thrownewRuntimeException(
  5. "Can'tcreatehandlerinsidethreadthathasnotcalledLooper.prepare()");
  6. }
  7. mQueue=mLooper.mQueue;//取得消息队列
  8. mCallback=null;
  9. }

3Java代码

  1. //不管调用哪个方法,最终执行的是
  2. publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis){
  3. booleansent=false;
  4. //取得消息队列
  5. MessageQueuequeue=mQueue;
  6. if(queue!=null){
  7. msg.target=this;//消息发出着是自己
  8. sent=queue.enqueueMessage(msg,uptimeMillis);//添加到消息队列中
  9. }
  10. else{
  11. RuntimeExceptione=newRuntimeException(
  12. this+"sendMessageAtTime()calledwithnomQueue");
  13. Log.w("Looper",e.getMessage(),e);
  14. }
  15. returnsent;
  16. }
  17. finalbooleanenqueueMessage(Messagemsg,longwhen){
  18. if(msg.when!=0){
  19. thrownewAndroidRuntimeException(msg
  20. +"Thismessageisalreadyinuse.");
  21. }
  22. if(msg.target==null&&!mQuitAllowed){
  23. thrownewRuntimeException("Mainthreadnotallowedtoquit");
  24. }
  25. synchronized(this){
  26. if(mQuiting){
  27. RuntimeExceptione=newRuntimeException(
  28. msg.target+"sendingmessagetoaHandleronadeadthread");
  29. Log.w("MessageQueue",e.getMessage(),e);
  30. returnfalse;
  31. }elseif(msg.target==null){
  32. mQuiting=true;
  33. }
  34. msg.when=when;
  35. Messagep=mMessages;
  36. //之前没有其他消息了,MessageQueue中当前消息mMessages就是传递进来的msg
  37. if(p==null||when==0||when<p.when){
  38. msg.next=p;
  39. mMessages=msg;
  40. this.notify();//唤醒
  41. }else{
  42. //之前有其他消息了,将传递的msg放到适合的位置,根据when
  43. Messageprev=null;
  44. while(p!=null&&p.when<=when){
  45. prev=p;
  46. p=p.next;
  47. }
  48. msg.next=prev.next;
  49. prev.next=msg;
  50. this.notify();//唤醒
  51. }
  52. }
  53. returntrue;
  54. }

4Java代码

  1. publicstaticfinalvoidloop(){
  2. Looperme=myLooper();
  3. MessageQueuequeue=me.mQueue;
  4. while(true){//死循环
  5. Messagemsg=queue.next();//当队列中没有消息时会阻塞
  6. if(msg!=null){
  7. if(msg.target==null){//消息没有发送者时,退出消息循环
  8. //Notargetisamagicidentifierforthequitmessage.
  9. return;
  10. }
  11. if(me.mLogging!=null)me.mLogging.println(
  12. ">>>>>Dispatchingto"+msg.target+""
  13. +msg.callback+":"+msg.what
  14. );
  15. //调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler
  16. msg.target.dispatchMessage(msg);
  17. if(me.mLogging!=null)me.mLogging.println(
  18. "<<<<<Finishedto"+msg.target+""
  19. +msg.callback);
  20. msg.recycle();
  21. }
  22. }
  23. }
  24. finalMessagenext(){
  25. booleantryIdle=true;
  26. while(true){
  27. synchronized(this){
  28. //没有消息的或,会阻塞
  29. try{
  30. if(mMessages!=null){
  31. if(mMessages.when-now>0){
  32. Binder.flushPendingCommands();
  33. this.wait(mMessages.when-now);
  34. }
  35. }else{
  36. Binder.flushPendingCommands();
  37. this.wait();
  38. }
  39. }
  40. catch(InterruptedExceptione){
  41. }
  42. }
  43. }
  44. }

总结

Handler作用:

1. 执行计划任务

2. 线程间通信

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

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

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

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics