android开发-----message

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()
2  
3 public final Message obtainMessage(int what)
4  
5 public final Message obtainMessage(int what, Object obj)
6  
7 public final Message obtainMessage(int what, int arg1, int arg2)
8  
9 public final Message obtainMessage(int what, int arg1, int arg2, Object obj)

obtainmessage()是从消息池中拿来一个msg 不须要另开辟空间new函数

new须要从新申请,效率低,obtianmessage能够循环利用;工具

[java]  view plain copy
  1. //use Handler.obtainMessage(),instead of msg = new Message();  
  2. //because if there is already an Message object,that not be used by   
  3. //any one ,the system will hand use that object,so you don't have to   
  4. //create and object and allocate memory.  
  5. //it  is also another example of object recycling and reusing in android.  
  6.     Message msg = mHandler.obtainMessage();  
  7.     msg.what = UPDATE_LISTVIEW;  
  8.     msg.obj = current + "/" + total + "songs";  
  9.     //this method is called from worker Thread,so we cannot update UI from here.  
  10.     msg.sendToTarget();  
在看下面代码:
[java]  view plain copy
  1. Message msg = handler.obtainMessage();  
  2.                         msg.arg1 = i;  
  3.                         msg.sendToTarget();   
  4.   
  5.   
  6. Message msg=new Message();  
  7.     msg.arg1=i;  
  8.     handler.sendMessage(msg);  

第一种写法是message 从handler 类获取,从而能够直接向该handler 对象发送消息,第二种写法是直接调用 handler 的发送消息方法发送消息。

C、删除消息

删除在消息队列中未处理的消息oop

1 public final void removeMessages(int what)
2  
3 public final void removeMessages(int what, Object object)

D、发送消息post

1 public final boolean sendMessage(Message msg)
2  
3 public final boolean sendMessageDelayed(Message msg, long delayMillis)
4  
5 public final boolean post(Runnable r)
6  
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:

1 public Handler()
2  
3 public Handler(Callback callback)

建立与指定线程相关联的Handler:

1 public Handler(Looper looper)
2  

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;
03        
04       public void run() {
05           Looper.prepare();
06            
07           mHandler = new Handler() {
08               public void handleMessage(Message msg) {
09                   // process incoming messages here
10               }
11           };
12            
13           Looper.loop();
14       }
15 }
相关文章
相关标签/搜索