消息处理机制 Handler Looper Message MessageQueue

来源:互联网 发布:misuo加密软件怎样 编辑:程序博客网 时间:2024/06/10 15:29
感谢师父的帮助和其他大神的帖子。

本文分为两个部分:
    1. 线程间通信机制说明。
    2. Handler Looper Message MessageQueue类常用方法解读。

继承关系:

线程间通信机制说明:
    这四个类组合使用构成了Android线程间通信机制,它们都继承于android.os类。
    在Android中,程序一开始运行就启动了ActivityThread(主线程,也叫UI线程),这个线程用来处理UI相关的任务。为了保证UI线程的高响应速度,规定在开发过程中应尽可能的把耗时操作(I/O等)放在子线程(其他线程)中执行。有些情景是把耗时操作处理完或者正在处理的时候就需要更新UI显示,但如果耗时操作和UI任务不在同一个线程中进行,就需要将子线程中的“任务完成情况”(消息Message)发送到主线程中去,让主线程依照这个消息对UI进行相应的更新等操作。
    这个 “将子线程的消息发送到主线程(将一个线程的消息发送到其他线程)” 的过程就是线程间通信。
    这个过程是: handler(处理者)调用send/post系列方法把Message(消息)添加到MessageQueue(消息队列)里,然后Looper(轮循者)将MessageQueue中的Message使用handler里面的一个回调方法传给handler的handleMessage()方法对消息进行处理。
    在线程间通信整个过程中,send/post(发送消息)方法调用是在子线程(发送消息的线程)完成的, handlerMessage()(处理消息)方法是在主线程(接收消息的线程)调用的。这样就完成了把消息从一个线程发送到另一个线程。
       当我们需要跨线程交互的时候,我们的只需要持有交互线程的handler就可以操作交互线程了
    但是经常也会使用handler来实现一些代码的动态跳转,更新等任务。
    Handler说明:Handler(消息管理者),负责发送消息(send/post)和处理(handleMessage())消息。 每一个线程可以有若干个Handler
    Message说明:Message(消息),封装了一些常量和方法,整个消息传递过程传递的对象就是Message对象。每一个Handler可以发送若干个Message
    MessageQueue说明:MessageQueue(消息队列),保存消息,handler调用send/post会把消息存到队列里,looper会取出消息。每一个线程只能有一个MessageQueue
    Looper说明:Looper(轮循者),不断循环检查MessageQueue里面是否有消息,有的话就发送给对应的Handler,Handler再对消息进行处理。每一个线程只能有一个Looper
    

Handler类方法详解
    构造方法
            1. 无参构造方法
, 此时创建的Handler默认的Looper是当前线程的looper,在主线程创建Handler时默认Looper是主线程的Looper。
            2. (Callback)构造方法
,制定一个回调对象,直接在handlerMessage()方法中写处理消息的逻辑。
            3. (Looper)构造方法
,传入一个Looper,代码中这个Looper是主线程Looper。
            4. (Looper,Callback)构造方法:
,传入刚才定义的Looper和Callback即可。
    常用方法
            1. 创建消息的方法Message对象可以new出来,但是推荐使用Handler.obtain()系列方法创建一个Message。obtain系列方法实际上是调用Message类中的obtain()方法来获取一个空的Message对象然后给其相应参数赋值,源码如下:

,即Message类维护着一个消息池,当前信息对象是sPool,每次从池子中拿出一个Message对象,sPool就指向下一个Message。池子的最大值是50,源码里有写出
,这样的设计可以提高Message的复用率,避免不断创建新的Message占用大量内存空间。
                    ⑴ obtainMessage(); 直接从池子中拿出一个空的Message
                    ⑵ obtainMessage(int what);
                    ⑶ obtainMessage(int what, Object obj);
                    ⑷ obtainMessage(int what, int arg1, int arg2);
                    ⑸ obtainMessage(int what, int arg1, int arg2, Object obj);
                    Message对象有这些属性(变量),供开发者使用此对象传递信息。一般的,what用来标识消息,这样的好处是处理消息的时候就可以使用switch判断在一个handler中对不同标识的消息进行不同的处理。arg1、arg2、obj这几个都是用来携带信息的,这三个基本可以满足任何信息的携带需求了。
                    ⑹ getPostMessage(Runnable r);
                    ⑺ getPostMessage(Runnable r, Object token);
                    这两个方法是新添加的方法,在方法内部也会调用obtain无参方法,然后将r和token分别赋给message的callback和obj属性。
            2. 发送消息的方法
                    Handler发送消息的实质其实是把消息交给MessageQueue,不管什么方法发送的消息最后都会走这一步
,而这个方法就是MessageQueue类的

给队列增加数据的方法。即发送消息其实是把消息交给MessageQueue。
                    Post系列:Post系列方法都会调用

这个方法弄出来一个Message对象,把Runnable接口实例作为Message的一个属性,然后调用Send系列方法发送消息。  注: 以下方法中uptimeMills参数的基准时间是Android.os.SystemClock.uptimeMills().  (PostAtTime/SendMessageAtTime)
                    ⑴ post(Runnable r);
                            传入一个Runnable接口实例,在这个接口实例的run方法中(主线程)更新UI的逻辑
     
,也可以写匿名类实现run方法。
                    ⑵ postAtTime(Runnable r, long uptimeMills);   
                            指定一个时间(毫秒值)来发送消息,
           
,在当前时间的1s后发送消息。
                    ⑶ postAtTime(Runnable r, Object token, long uptimeMills);
                            指定一个时间(毫秒值)来发送消息,其中token这个参数会在调用getPostMessage方法时被封装成Message的obj属性。
                    ⑷ postDelayed(Runnable r, long delayMills);
                            延迟一个时间(毫秒值)来发送消息,
            
,在当前时间的1s后发送消息。
                    ⑸ postAtFrontOfQueue(Runnable t);
                            发送一个消息,并把消息插到当前消息队列的第一位。
                    Send系列:
                    ⑹ sendMessage(Message msg);
                            发送一个消息
                    ⑺ sendEmptyMessage(int what);
                            发送一个空消息
                    ⑻ sendEmptyMessageDelayed(int what, long delayMills);
                            延迟一个时间(毫秒值)发送一个空消息
                    ⑼ sendMessageAtTime(int what, long uptimeMills);
                            指定一个时间(毫秒值)发送一个空消息
                    ⑽ sendMessageDelayed(Message msg, long delayMills);
                            延迟一个时间(毫秒值)发送一个消息
                    ⑾ sendMessageAtTime(Message msg, long uptimeMills);
                            指定一个时间(毫秒值)发送一个消息
                    ⑿ sendMessageAtFrontOfQueue(Message msg);
                            发送一个消息,并把消息插到当前消息队列的第一位。
            3. 处理消息的方法:  
                    ⑴ 在调用post方法发送消息是传入的runnable对象的run方法里处理消息。
                    ⑵ 在new Handler的时候传入Handler.callback对象,在该对象的handleMessage方法里处理消息。注:该方法有返回值,返回值的作用下面会说到。
                    ⑶ handleMessage(Message msg);  这个方法是Hanlder类中定义的空方法,如有需要,可以重写该方法来处理消息。
                 处理消息的过程:
                     处理消息的时候先由Looper调用dispatchMessage(Message msg)分发消息,然后在dispatchMessage()中各种判断对应不同的执行逻辑。
                     先调用dispatchMessage(Message msg);
                            看下源码,
                
,当要发送的消息没有绑定runnable对象,并且Hanlder对象本身的callback属性没有赋值,就调用handleMessage()。如果使用post发送消息,在每个post方法里会调用getPostMessage方法把传进来的runnable对象赋给msg的callback属性,即msg绑定了runnable对象,就会走if(msg.callback!=null)为真的判断,使用runnable对象的run方法来处理消息;在Handler的构造方法可以选择是否传入callback对象,这个对象是Handler里面的callback接口对象,如果传入callback对象即Handler对象本身的callback属性有了值,则会走if(mCallback!=null)的判断,使用传入的callback对象的handleMessage方法处理消息,要注意的是,mCallback.handleMessage方法会返回一个布尔值,如果返回真则方法结束,返回假则继续运行创建Handler时重写的handleMessage方法来处理消息。
                            
                 
            4. 其他方法
                     ⑴ hasMessage(Handler h, int what, Object obj);     
                             判断消息队列中是否有某个消息。
                     ⑵ hasMessage(Handler h, Runnable r, Object obj);  
                             判断消息队列中是否有某个消息。
                     ⑶ removeCallbacks(Runnable r);  调用removeMessage(int what, Object obj);
                     ⑷ removeCallbacks(Runnable r, Object token);  调用removeMessage(int what, Object obj);
                     ⑸ removeMessages(int what);  
                             调用MessageQueue中的removeMessages()删除当前队列中的标记为what的Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池。           
                     ⑹ removeMessages(int what, Object obj);
                             调用MessageQueue中的removeMessages()删除当前队列中的使用的Runnable实例为传入的Runnable的Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池。     
                     ⑺ removeCallBacksAndMessages(Object token)
                             调用MessageQueue中的removeCallbackAndMessages()删除当前队列中的obj属性是传入的参数的所有Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池,如果此方法传入参数是null,则全部删除。
                     ⑻ getLooper();
                             获取当前handler绑定的looper对象
                     ⑼ enqueueMessage(MessageQueue queue, Message msg, long uptimeMills);
                             将Massage保存到队列中,所有的发送消息的方法最终都调用了此方法
                    
                    

Message类方法详解:消息实体类,该类实现了Parcelable接口。
    构造方法:无参构造,但是不推荐使用构造方法直接创建实例。
     常用方法
                1. 创建消息的方法:此处创建消息的方法就是Handler中obtain系列方法最终调用的方法。
                      ⑴ obtain(); 从消息池中拿出一个消息对象。
                      ⑵ obtain(Message orig); 将传入的消息对象赋给从消息池中新拿出来的对象。
                      ⑶ obtain(Handler h); 从消息池中拿出一个消息对象,给target属性赋上h。
                      ⑷ obtain(Handler h, Runnable r); 从消息池中拿出一个消息对象,给target赋值h,给callback属性赋值r。
                      ⑸ obtain(Handler h, int what); 从消息池中拿出一个消息对象,给target赋值h,给what赋值what。
                      ⑹ obtain(Hander h, int what, int arg1, int arg2);
                      ⑺ obtain(Hander h, int what, Object obj);
                      ⑻ obtain(Hander h, int what, arg1, arg2, Object obj);
                            从消息池中拿出一个消息对象,给对应的属性赋值。
                2. 发送消息的方法
                        sendToTarget():发送消息到制定target,使用之前要制定target(Hnadler)
                3. set/get方法
                        ⑴ getWhen();  获得消息发送时的时间(毫秒值)
                        ⑵ getTarget(); 获得发送消息的Handler对象
                        ⑶ getCallback(); 获得处理消息的callback对象
                        ⑷ getData(); 获取Message的data属性值,如果data为null,则new一个Bundle对象给data
                        ⑸ peekData(); 和getData()作用类似,获取Message的data属性值,但不判断data是否为null,即可能返回的值是null
                        ⑹ setData(Bundle data); 设置Message的data属性
                        ⑺ setTarget(Handler h); 设置发送Message的Handler
                4. 其他方法
                        ⑴ copyFrom(Message o); 赋值传入消息对象的部分属性
  
                        ⑵ recycle(); 如果该消息没有处于正在处理的状态,则回收消息到消息池。



Looper类方法详解:轮循者,不断检查消息队列,如果有,从前到后依次拿出消息交给处理者处理。
        主线程启动时会创建出自己的looper轮询消息,当其它线程想创建属于自的handler和looper的话,Looper.myLooper是个空的,需要手动去创建,Looper.prepare()创建一个Looper,通过looper.loop开启一个死循环去轮询消息,这时候就会卡死在Looper.loop这个地方,后面的代码得不到执行,除非调用looper.quit()方法。这个时候我们可以发送自己的消息去处理相应的逻辑,这个线程将一直存在。
        然而主线程ActivityThread.main()

        这也是开启了个死循环一直轮序消息,其实并不太占用资源的,当有消息的时候激活,没消息的时候休眠,当一旦loop跳出,就会抛出异常。
        looper传入哪个handler,那么这个handler就是处理的哪个looper对应的messagequeue的消息。
在线程的构造方法里取myLooper其实执行它的还是主线程里的Looper

当在run方法真正跑起来的时候取得myLooper才是当前线程的looper,如果没有创建过的话默认是null的,所以在子线程中我们要手动创建一下,如:


    方法
        1. 创建looper的方法:    
                prepare();  此方法用来创建一个Looper,
                prepare(boolean quitAllowed); 传入一个布尔值,
会对ThreadLocal对象的get方法返回值是否存在进行判断,最终调用Looper的构造方法,
。如果Threadlocal.get返回值不为null,则说明已经创建过looper了,为了保证每一个线程只能有一个looper,则当重新创建Looper时会报异常。
    
            2. 获取属性的方法:
                getMainLooper(); 获取当前程序的主线程looper
                myLooper();  获取当前线程的looper
                myQueue();  获取当前looper绑定的MessageQueue
                isCurrentThread(); 返回布尔值,判断当前线程是否是Looper绑定的线程。
                getThread();  获取当前线程对象。
                getQueue(); 获取当前MessageQueue对象。
            3. looper的核心方法(运行方法):
                loop(); 
                    在这个方法里面会做一系列的判断(各种判空),核心有两句,一句是
,获取消息,另一句是
,调用Message的Handler对象的dispatchMessage();方法处理消息。   这个方法如果不手动结束会一直运行,
,这是个死循环。
            4. 其他方法:
                quit();
                quitSafely();
                    这两个方法最终会调用MessageQueue中的方法,用于让looper停止活动。

, MessageQueue中的
最后会调用MessageQueue的removeAllMessafeLocked()和removeAllFutureMessageLocked()方法。(消息分为非延迟消息和延迟消息,延迟消息就是通过send/postxxxAtTime,send/postxxxDelayed设置一定时间后处理的消息)removeAllMessageLocked()方法会清空队列中所有的消息,而后者只会清空延时的消息,保留非延迟消息,继续处理,当处理完所有消息,Looper就会“停止”(无消息可处理)。此时,再调用send/post方法就会返回false(即无法添加到队列),因为在quit方法里面会令mQuitting这个变量为true,而在MessageQueue添加消息的方法(enqueueMessage)里面会对mQuitting进行判断,如果该变量为True,则返回false。而MessageQueue类没有提供更改mQuitting变量的方法,故一旦使用quit/quitSafely方法,就再也不能往消息队列中添加消息了。

MessageQueue类主要方法解释:这个类提供了很多方法供handler,looper调用来对消息队列做出一些处理,我们一般不会直接和这个类打交道,所以只简单分析一下即可。
    Handler调用的方法:
        enqueueMessage(Message msg, long when);   将消息存放入MessageQueue中的方法
        hasMessage(Handler h, int what, Object object);    返回布尔值,判断队列中是否有对应的Message
        hasMessage(Handler h, Runnable r, Object object);    返回布尔值,判断队列中是否有对应的Message
        remove系列方法, 按指定参数删除消息队列中的消息。
    Looper调用的方法
        next();   找到队列中的下一个消息,并返回。Looper就是调用这个方法不断从队列中拿到消息。
        quit();    清空消息队列中的消息,来使looper停止工作。
    

   
总结

  
本文分为两个部分:
    1. 线程间通信机制说明。
    2. Handler Looper Message MessageQueue类常用方法解读。

继承关系:

线程间通信机制说明:
    这四个类组合使用构成了Android线程间通信机制,它们都继承于android.os类。
    在Android中,程序一开始运行就启动了ActivityThread(主线程,也叫UI线程),这个线程用来处理UI相关的任务。为了保证UI线程的高响应速度,规定在开发过程中应尽可能的把耗时操作(I/O等)放在子线程(其他线程)中执行。有些情景是把耗时操作处理完或者正在处理的时候就需要更新UI显示,但如果耗时操作和UI任务不在同一个线程中进行,就需要将子线程中的“任务完成情况”(消息Message)发送到主线程中去,让主线程依照这个消息对UI进行相应的更新等操作。
    这个 “将子线程的消息发送到主线程(将一个线程的消息发送到其他线程)” 的过程就是线程间通信。
    这个过程是: handler(处理者)调用send/post系列方法把Message(消息)添加到MessageQueue(消息队列)里,然后Looper(轮循者)将MessageQueue中的Message使用handler里面的一个回调方法传给handler的handleMessage()方法对消息进行处理。
    在线程间通信整个过程中,send/post(发送消息)方法调用是在子线程(发送消息的线程)完成的, handlerMessage()(处理消息)方法是在主线程(接收消息的线程)调用的。这样就完成了把消息从一个线程发送到另一个线程。
       当我们需要跨线程交互的时候,我们的只需要持有交互线程的handler就可以操作交互线程了
    但是经常也会使用handler来实现一些代码的动态跳转,更新等任务。
    Handler说明:Handler(消息管理者),负责发送消息(send/post)和处理(handleMessage())消息。 每一个线程可以有若干个Handler
    Message说明:Message(消息),封装了一些常量和方法,整个消息传递过程传递的对象就是Message对象。每一个Handler可以发送若干个Message
    MessageQueue说明:MessageQueue(消息队列),保存消息,handler调用send/post会把消息存到队列里,looper会取出消息。每一个线程只能有一个MessageQueue
    Looper说明:Looper(轮循者),不断循环检查MessageQueue里面是否有消息,有的话就发送给对应的Handler,Handler再对消息进行处理。每一个线程只能有一个Looper
    

Handler类方法详解
    构造方法
            1. 无参构造方法
, 此时创建的Handler默认的Looper是当前线程的looper,在主线程创建Handler时默认Looper是主线程的Looper。
            2. (Callback)构造方法
,制定一个回调对象,直接在handlerMessage()方法中写处理消息的逻辑。
            3. (Looper)构造方法
,传入一个Looper,代码中这个Looper是主线程Looper。
            4. (Looper,Callback)构造方法:
,传入刚才定义的Looper和Callback即可。
    常用方法
            1. 创建消息的方法Message对象可以new出来,但是推荐使用Handler.obtain()系列方法创建一个Message。obtain系列方法实际上是调用Message类中的obtain()方法来获取一个空的Message对象然后给其相应参数赋值,源码如下:
,即Message类维护着一个消息池,当前信息对象是sPool,每次从池子中拿出一个Message对象,sPool就指向下一个Message。池子的最大值是50,源码里有写出
,这样的设计可以提高Message的复用率,避免不断创建新的Message占用大量内存空间。
                    ⑴ obtainMessage(); 直接从池子中拿出一个空的Message
                    ⑵ obtainMessage(int what);
                    ⑶ obtainMessage(int what, Object obj);
                    ⑷ obtainMessage(int what, int arg1, int arg2);
                    ⑸ obtainMessage(int what, int arg1, int arg2, Object obj);
                    Message对象有这些属性(变量),供开发者使用此对象传递信息。一般的,what用来标识消息,这样的好处是处理消息的时候就可以使用switch判断在一个handler中对不同标识的消息进行不同的处理。arg1、arg2、obj这几个都是用来携带信息的,这三个基本可以满足任何信息的携带需求了。
                    ⑹ getPostMessage(Runnable r);
                    ⑺ getPostMessage(Runnable r, Object token);
                    这两个方法是新添加的方法,在方法内部也会调用obtain无参方法,然后将r和token分别赋给message的callback和obj属性。
            2. 发送消息的方法
                    Handler发送消息的实质其实是把消息交给MessageQueue,不管什么方法发送的消息最后都会走这一步
,而这个方法就是MessageQueue类的
给队列增加数据的方法。即发送消息其实是把消息交给MessageQueue。
                    Post系列:Post系列方法都会调用
这个方法弄出来一个Message对象,把Runnable接口实例作为Message的一个属性,然后调用Send系列方法发送消息。  注: 以下方法中uptimeMills参数的基准时间是Android.os.SystemClock.uptimeMills().  (PostAtTime/SendMessageAtTime)
                    ⑴ post(Runnable r);
                            传入一个Runnable接口实例,在这个接口实例的run方法中(主线程)更新UI的逻辑
                                
,也可以写匿名类实现run方法。
                    ⑵ postAtTime(Runnable r, long uptimeMills);   
                            指定一个时间(毫秒值)来发送消息,
                    
,在当前时间的1s后发送消息。
                    ⑶ postAtTime(Runnable r, Object token, long uptimeMills);
                            指定一个时间(毫秒值)来发送消息,其中token这个参数会在调用getPostMessage方法时被封装成Message的obj属性。
                            
                    ⑷ postDelayed(Runnable r, long delayMills);
                            延迟一个时间(毫秒值)来发送消息,
                            
,在当前时间的1s后发送消息。
                    ⑸ postAtFrontOfQueue(Runnable t);
                            发送一个消息,并把消息插到当前消息队列的第一位。
                    Send系列:
                    ⑹ sendMessage(Message msg);
                            发送一个消息
                    ⑺ sendEmptyMessage(int what);
                            发送一个空消息
                    ⑻ sendEmptyMessageDelayed(int what, long delayMills);
                            延迟一个时间(毫秒值)发送一个空消息
                    ⑼ sendMessageAtTime(int what, long uptimeMills);
                            指定一个时间(毫秒值)发送一个空消息
                    ⑽ sendMessageDelayed(Message msg, long delayMills);
                            延迟一个时间(毫秒值)发送一个消息
                    ⑾ sendMessageAtTime(Message msg, long uptimeMills);
                            指定一个时间(毫秒值)发送一个消息
                    ⑿ sendMessageAtFrontOfQueue(Message msg);
                            发送一个消息,并把消息插到当前消息队列的第一位。
            3. 处理消息的方法:  
                    ⑴ 在调用post方法发送消息是传入的runnable对象的run方法里处理消息。
                    ⑵ 在new Handler的时候传入Handler.callback对象,在该对象的handleMessage方法里处理消息。注:该方法有返回值,返回值的作用下面会说到。
                    ⑶ handleMessage(Message msg);  这个方法是Hanlder类中定义的空方法,如有需要,可以重写该方法来处理消息。
                 处理消息的过程:
                     处理消息的时候先由Looper调用dispatchMessage(Message msg)分发消息,然后在dispatchMessage()中各种判断对应不同的执行逻辑。
                     先调用dispatchMessage(Message msg);
                            看下源码,
                
,当要发送的消息没有绑定runnable对象,并且Hanlder对象本身的callback属性没有赋值,就调用handleMessage()。如果使用post发送消息,在每个post方法里会调用getPostMessage方法把传进来的runnable对象赋给msg的callback属性,即msg绑定了runnable对象,就会走if(msg.callback!=null)为真的判断,使用runnable对象的run方法来处理消息;在Handler的构造方法可以选择是否传入callback对象,这个对象是Handler里面的callback接口对象,如果传入callback对象即Handler对象本身的callback属性有了值,则会走if(mCallback!=null)的判断,使用传入的callback对象的handleMessage方法处理消息,要注意的是,mCallback.handleMessage方法会返回一个布尔值,如果返回真则方法结束,返回假则继续运行创建Handler时重写的handleMessage方法来处理消息。
                            
                 
            4. 其他方法
                     ⑴ hasMessage(Handler h, int what, Object obj);     
                             判断消息队列中是否有某个消息。
                     ⑵ hasMessage(Handler h, Runnable r, Object obj);  
                             判断消息队列中是否有某个消息。
                     ⑶ removeCallbacks(Runnable r);  调用removeMessage(int what, Object obj);
                     ⑷ removeCallbacks(Runnable r, Object token);  调用removeMessage(int what, Object obj);
                     ⑸ removeMessages(int what);  
                             调用MessageQueue中的removeMessages()删除当前队列中的标记为what的Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池。           
                     ⑹ removeMessages(int what, Object obj);
                             调用MessageQueue中的removeMessages()删除当前队列中的使用的Runnable实例为传入的Runnable的Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池。     
                     ⑺ removeCallBacksAndMessages(Object token)
                             调用MessageQueue中的removeCallbackAndMessages()删除当前队列中的obj属性是传入的参数的所有Message,其中会调用p.recycleUnchecked()(在MessageQueue中)将Message全部属性重置为null(0),放入消息池,如果此方法传入参数是null,则全部删除。
                     ⑻ getLooper();
                             获取当前handler绑定的looper对象
                     ⑼ enqueueMessage(MessageQueue queue, Message msg, long uptimeMills);
                             将Massage保存到队列中,所有的发送消息的方法最终都调用了此方法
                    
                    

Message类方法详解:消息实体类,该类实现了Parcelable接口。
    构造方法:无参构造,但是不推荐使用构造方法直接创建实例。
     常用方法
                1. 创建消息的方法:此处创建消息的方法就是Handler中obtain系列方法最终调用的方法。
                      ⑴ obtain(); 从消息池中拿出一个消息对象。
                      ⑵ obtain(Message orig); 将传入的消息对象赋给从消息池中新拿出来的对象。
                      ⑶ obtain(Handler h); 从消息池中拿出一个消息对象,给target属性赋上h。
                      ⑷ obtain(Handler h, Runnable r); 从消息池中拿出一个消息对象,给target赋值h,给callback属性赋值r。
                      ⑸ obtain(Handler h, int what); 从消息池中拿出一个消息对象,给target赋值h,给what赋值what。
                      ⑹ obtain(Hander h, int what, int arg1, int arg2);
                      ⑺ obtain(Hander h, int what, Object obj);
                      ⑻ obtain(Hander h, int what, arg1, arg2, Object obj);
                            从消息池中拿出一个消息对象,给对应的属性赋值。
                2. 发送消息的方法
                        sendToTarget():发送消息到制定target,使用之前要制定target(Hnadler)
                3. set/get方法
                        ⑴ getWhen();  获得消息发送时的时间(毫秒值)
                        ⑵ getTarget(); 获得发送消息的Handler对象
                        ⑶ getCallback(); 获得处理消息的callback对象
                        ⑷ getData(); 获取Message的data属性值,如果data为null,则new一个Bundle对象给data
                        ⑸ peekData(); 和getData()作用类似,获取Message的data属性值,但不判断data是否为null,即可能返回的值是null
                        ⑹ setData(Bundle data); 设置Message的data属性
                        ⑺ setTarget(Handler h); 设置发送Message的Handler
                4. 其他方法
                        ⑴ copyFrom(Message o); 赋值传入消息对象的部分属性
                            
                        ⑵ recycle(); 如果该消息没有处于正在处理的状态,则回收消息到消息池。
                            
                            
                        


Looper类方法详解:轮循者,不断检查消息队列,如果有,从前到后依次拿出消息交给处理者处理。
        主线程启动时会创建出自己的looper轮询消息,当其它线程想创建属于自的handler和looper的话,Looper.myLooper是个空的,需要手动去创建,Looper.prepare()创建一个Looper,通过looper.loop开启一个死循环去轮询消息,这时候就会卡死在Looper.loop这个地方,后面的代码得不到执行,除非调用looper.quit()方法。这个时候我们可以发送自己的消息去处理相应的逻辑,这个线程将一直存在。
        然而主线程ActivityThread.main()
        这也是开启了个死循环一直轮序消息,其实并不太占用资源的,当有消息的时候激活,没消息的时候休眠,当一旦loop跳出,就会抛出异常。
        looper传入哪个handler,那么这个handler就是处理的哪个looper对应的messagequeue的消息。
        
在线程的构造方法里取myLooper其实执行它的还是主线程里的Looper
当在run方法真正跑起来的时候取得myLooper才是当前线程的looper,如果没有创建过的话默认是null的,所以在子线程中我们要手动创建一下,如:


    方法
        1. 创建looper的方法:    
                prepare();  此方法用来创建一个Looper,
                prepare(boolean quitAllowed); 传入一个布尔值,
会对ThreadLocal对象的get方法返回值是否存在进行判断,最终调用Looper的构造方法,
。如果Threadlocal.get返回值不为null,则说明已经创建过looper了,为了保证每一个线程只能有一个looper,则当重新创建Looper时会报异常。
    
            2. 获取属性的方法:
                getMainLooper(); 获取当前程序的主线程looper
                myLooper();  获取当前线程的looper
                myQueue();  获取当前looper绑定的MessageQueue
                isCurrentThread(); 返回布尔值,判断当前线程是否是Looper绑定的线程。
                getThread();  获取当前线程对象。
                getQueue(); 获取当前MessageQueue对象。
            3. looper的核心方法(运行方法):
                loop(); 
                    在这个方法里面会做一系列的判断(各种判空),核心有两句,一句是
,获取消息,另一句是
,调用Message的Handler对象的dispatchMessage();方法处理消息。   这个方法如果不手动结束会一直运行,
,这是个死循环。
            4. 其他方法:
                quit();
                quitSafely();
                    这两个方法最终会调用MessageQueue中的方法,用于让looper停止活动。
, MessageQueue中的
最后会调用MessageQueue的removeAllMessafeLocked()和removeAllFutureMessageLocked()方法。(消息分为非延迟消息和延迟消息,延迟消息就是通过send/postxxxAtTime,send/postxxxDelayed设置一定时间后处理的消息)removeAllMessageLocked()方法会清空队列中所有的消息,而后者只会清空延时的消息,保留非延迟消息,继续处理,当处理完所有消息,Looper就会“停止”(无消息可处理)。此时,再调用send/post方法就会返回false(即无法添加到队列),因为在quit方法里面会令mQuitting这个变量为true,而在MessageQueue添加消息的方法(enqueueMessage)里面会对mQuitting进行判断,如果该变量为True,则返回false。而MessageQueue类没有提供更改mQuitting变量的方法,故一旦使用quit/quitSafely方法,就再也不能往消息队列中添加消息了。
        


MessageQueue类主要方法解释:这个类提供了很多方法供handler,looper调用来对消息队列做出一些处理,我们一般不会直接和这个类打交道,所以只简单分析一下即可。
    Handler调用的方法:
        enqueueMessage(Message msg, long when);   将消息存放入MessageQueue中的方法
        hasMessage(Handler h, int what, Object object);    返回布尔值,判断队列中是否有对应的Message
        hasMessage(Handler h, Runnable r, Object object);    返回布尔值,判断队列中是否有对应的Message
        remove系列方法, 按指定参数删除消息队列中的消息。
    Looper调用的方法
        next();   找到队列中的下一个消息,并返回。Looper就是调用这个方法不断从队列中拿到消息。
        quit();    清空消息队列中的消息,来使looper停止工作。
    

   
总结



                
                
                
                
        
              







    
0 0