MessageQueue:消息队列,使用FIFO规则执行,每一个线程只可以拥有一个MessageQueue,在创建Looper对象会创建一个
MessageQueue用来容纳Message队列的,其中的Message是由Looper来分发的,Message不能直接添加到MessageQueue中,而是要通过与Looper关联的Handler去添加。
创建一个线程的时候,并不会自动创建其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中删除,同时放入到消息池中。
Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了两个额外的 int字段和一个object字段,这样在大部分情况下,使用者就不需要再做内存分配工作了。虽然Message的构造函数是public的,但是最好是使用Message.obtain( )或Handler.obtainMessage( )函数来获取Message对象,因为Message的实现中包含了回收再利用的机制,可以提供效率。
B、创建消息
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、删除消息 删除在消息队列中未处理的消息
1 | public final void removeMessages( int what) |
3 | public final void removeMessages( int what, Object object) |
D、发送消息
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) |
3、Looper
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()
4、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 |