博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android开发-----message
阅读量:6845 次
发布时间:2019-06-26

本文共 5192 字,大约阅读时间需要 17 分钟。

  hot3.png

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()
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] 
  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] 
  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、删除消息

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

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

D、发送消息

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)

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:

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 }

转载于:https://my.oschina.net/durong/blog/56322

你可能感兴趣的文章
求浮点数的整数次幂
查看>>
请求https错误: unable to find valid certification path to requested target
查看>>
从零开始撸一个Fresco之总结
查看>>
[python skill]Python 中 NaN 和 None 的详细比较
查看>>
「架构技术专题」作为java程序员的你还不知道网站架构的演化(2)?
查看>>
业界 | Nature:AI为什么总是歧视重重?
查看>>
9- Flask构建弹幕微电影网站-后台逻辑(一)
查看>>
Linux_服务器_03_xxx is not in the sudoers file.This incident will be reported.的解决方法
查看>>
程序员的桌面(家)
查看>>
jQuery Validate自定义各种验证方法
查看>>
订阅制女装搭配电商平台秘盒幻想曲已完成数百万元天使轮融资
查看>>
阿里云融合CDN解决方案
查看>>
初识 JSP---(转发和重定向)
查看>>
web.py源码分析: 模板(3)
查看>>
Javascript自动化文档工具:YUI Doc, JSDoc 3, JSDuck等比较
查看>>
汉语言处理包 HanLP 1.7.3 发布,常规维护版本
查看>>
Visual D 0.49.0 发布,支持 Visual Studio 2019
查看>>
IT人必看!2018年上半年云栖大会300份干货PPT免费开放!最前沿的技术都在这了!...
查看>>
nignx
查看>>
solr6.6初探之分词篇
查看>>