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

Looper是消费者,Handler是生产者(同时Looper消费后,也会通知Handler),MessageQueue是消息队列,队列的实现方式是链表,Message是链表的一个节点。 我们的程序基本上之和Handler打交道。



    线程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。

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

    一个在新线程中使用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();

    1 Java代码

       
       
    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. }

    2 Java代码

       
       
    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. }

    3 Java代码

       
       
    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. }

    4 Java代码

       
       
    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。

    你可能感兴趣的:(android)