MessageQueue:消息队列,使用FIFO规则执行,每个线程只能够拥有一个MessageQueue,在建立Looper对象会建立一个html
MessageQueue用来容纳Message队列的,其中的Message是由Looper来分发的,Message不能直接添加到MessageQueue中,而是要经过与Looper关联的Handler去添加。java
建立一个线程的时候,并不会自动建立其MessageQueue。一般使用一个Looper对象对该线程的MessageQueue进行管理。主线程建立时,会建立一
个默认的Looper对象,而Looper对象的建立,将自动建立一个Message Queue。其余非主线程,不会自动建立Looper,要须要的时候,经过调
用prepare函数来实现。
Message消息对象:MessageQueue中存放的对象,一个MEssageQueue中能够包含多个MEssage,能够经过Message.obtain()或者Handle.obtainMessage()获取Message对象,可是这并不必定是直接建立一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出返回这个实例,若是消息池中没有可用的MEssage实例i,则采用给定的参数建立一个Message对象,调用removeMessage()时,将Message从MessageQueue中删除,同时放入到消息池中。android
Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了两个额外的 int字段和一个object字段,这样在大部分状况下,使用者就不须要再作内存分配工做了。虽然Message的构造函数是public的,可是最好是使用Message.obtain( )或Handler.obtainMessage( )函数来获取Message对象,由于Message的实现中包含了回收再利用的机制,能够提供效率。 app
B、建立消息ide
1 |
public final Message obtainMessage() |
3 |
public final Message obtainMessage( int what) |
5 |
public final Message obtainMessage( int what, Object obj) |
7 |
public final Message obtainMessage( int what, int arg1, int arg2) |
9 |
public final Message obtainMessage( int what, int arg1, int arg2, Object obj) |
obtainmessage()是从消息池中拿来一个msg 不须要另开辟空间new函数
new须要从新申请,效率低,obtianmessage能够循环利用;工具
- //use Handler.obtainMessage(),instead of msg = new Message();
- //because if there is already an Message object,that not be used by
- //any one ,the system will hand use that object,so you don't have to
- //create and object and allocate memory.
- //it is also another example of object recycling and reusing in android.
- Message msg = mHandler.obtainMessage();
- msg.what = UPDATE_LISTVIEW;
- msg.obj = current + "/" + total + "songs";
- //this method is called from worker Thread,so we cannot update UI from here.
- msg.sendToTarget();
在看下面代码:
- Message msg = handler.obtainMessage();
- msg.arg1 = i;
- msg.sendToTarget();
-
-
- Message msg=new Message();
- msg.arg1=i;
- handler.sendMessage(msg);
第一种写法是message 从handler 类获取,从而能够直接向该handler 对象发送消息,第二种写法是直接调用 handler 的发送消息方法发送消息。
C、删除消息
删除在消息队列中未处理的消息oop
1 |
public final void removeMessages( int what) |
3 |
public final void removeMessages( int what, Object object) |
D、发送消息post
1 |
public final boolean sendMessage(Message msg) |
3 |
public final boolean sendMessageDelayed(Message msg, long delayMillis) |
5 |
public final boolean post(Runnable r) |
7 |
public final boolean postDelayed(Runnable r, long delayMillis) |
三、Looperui
frameworks\base\core\java\android\Os\Looper.java
Looper是线程用来运行消息循环的。线程自己是没有消息循环的,须要在线程中调用perpare函数,而后调用loop去处理消息。在Android中,系统在启动主线程的时候会自动为之创建一个Looper。
Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理。handler其实能够看作是一个工具类,用来向消息队列中插入消息的。
创建本线程的Looper:
public static final void prepare()
运行本线程的Looper:
public static final void loop()
注意:写在Looper.loop()以后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会停止,其后的代码才能得以运行。
获取本线程的Looper:
public static final Looper myLooper()
相似的 Looper.getMainLooper() 用于获取主线程的Looper对象。
获取主线程的Looper:
public synchronized static final Looper getMainLooper()
四、Handler
frameworks\base\core\java\android\Os\Handler.java
Handler是用来发送和处理与线程相关联的Message和Runnable对象的。每一个Handler都与一个单独的线程以及线程消息队列相关联的。当你建立Handler时,Handler就与线程以及线程消息队列绑定了,从那之后,Handler就能够将 Message和Runnable发送给对应的消息队列,而且可以处理从消息队列中出来的消息。
一般是经过Handler对象来与Looper进行交互的。Handler可看作是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。
默认状况下Handler会与其被定义时所在线程的Looper绑定,好比,Handler在主线程中定义,那么它是与主线程的Looper绑定。
mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).(这里Looper.myLooper()获取本线程的Looper:相似的 Looper.getMainLooper() 用于获取主线程的Looper对象。)
在非主线程中直接new Handler() 会报以下的错误:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
缘由是非主线程中默认没有建立Looper对象,须要先调用Looper.prepare()启用Looper。
A、建立Handler:
建立与本地线程相关联的Handler:
3 |
public Handler(Callback callback) |
建立与指定线程相关联的Handler:
1 |
public Handler(Looper looper) |
3 |
public Handler(Looper looper, Callback callback) |
E、处理消息
在Looper的loop函数中循环取出MessageQueue的接收消息队列中的消息,而后调用Hander的dispatchMessage函数对消息进行处理,至于如何处理(相应消息)则由用户指定(三个方法,优先级从高到低:Message里面的Callback,一个实现了Runnable接口的对象,其中run函数作处理工做;Handler里面的mCallback指向的一个实现了Callback接口的对象,里面的handleMessage进行处理;处理消息 Handler对象对应的类继承并实现了其中handleMessage函数,经过这个实现的handleMessage函数处理消息)。
(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。
把下面例子中的mHandler声明成类成员,在主线程经过mHandler发送消息便可。
Android官方文档中Looper的介绍:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.
01 |
class LooperThread extends Thread { |
02 |
public Handler mHandler; |
07 |
mHandler = new Handler() { |
08 |
public void handleMessage(Message msg) { |
09 |
// process incoming messages here |