Android中的消息处理机制由四个部分组成:Message、Handler、MessageQueue和Looper,并且MessageQueue封装在Looper中,我们一般不直接与MQ打交道。

一、Looper

Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。

一个线程中只有一个Looper对象,一个Looper对象只有一个MessageQueue,而一个线程中可以有多个hander,可以根据需要为hander设置不同的Looper进行处理。

那么如何将一个线程变为Looper线程呢?其实很简单,只需要在该线程中加入以下两行代码:

public class LooperThread extends Thread {
@Override
public void run() {
// 将当前线程初始化为Looper线程
Looper.prepare(); // ...其他处理,如实例化handler // 开始循环处理消息队列
Looper.loop();
}
}

调用Looper.prepare()方法是为了为当前线程的ThreadLocal(关于ThreadLocal的解释详见http://blog.csdn.net/qjyong/article/details/2158097)设值(就我的理解就是创建一个新的Looper给当前线程使用,当一个线程有了Looper对象后该线程就可变为Looper线程了)。然后再调用Looper.loop()方法就让该Looper线程开始工作了,Looper会不断的从自己的MessageQueue中取出队头的消息进行处理。

除了prepare()和loop()Looper类还有其它的一些方法:

Looper.myLooper()   得到当前线程looper对象

getThread()   得到looper对象所属线程

quit()            方法结束looper循环

二、Handler

handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。handler创建时会关联一个looper,默认的构造方法将关联当前线程的looper,不过这也是可以set的。

有了handler之后,我们就可以使用 post(Runnable)postAtTime(Runnable, long)postDelayed(Runnable, long)sendEmptyMessage(int),

sendMessage(Message)sendMessageAtTime(Message, long)和 sendMessageDelayed(Message, long)这些方法向MQ上发送消息了;使用dispatchMessage(

Message msg)与方法handleMessage(Message msg)。光看这些API你可能会觉得handler能发两种消息,一种是Runnable对象,一种是message对象,这是直观的理解,但其实post发出的Runnable对象最后都被封装成message对象了,一般我们使用Handler的的sendMessage()方法来发送消息到消息队列中,使用handleMessage()方法来处理消息队列中当前handler所发送的消息

Handler的作用:

1.handler可以在任意线程发送消息,这些消息会被添加到该handler关联的MQ上。

2.handler是在它关联的looper线程中处理消息的。

这就是android中为什么不能在其他非主线程中更新UI的问题。android的主线程也是一个looper线程,我们在其中创建的handler默认将关联主线程MQ。因此,利用handler的一个solution就是在activity中创建handler并将其引用传递给worker thread,worker thread执行完任务后使用handler发送消息通知activity更新UI(我的理解就是主线程开启时会自动创建有对应的Handler、Looper和MessageQueue,其所做的操作就是当对界面进行修改时会发送一条消息到消息队列中由Handler取出去进行处理,单当开启子线程后子线程中不会自动创建Handler、Looper和MessageQueue,这样当进行界面匀速修改时是没有消息去通知当前主线程的handler去处理这一动作的,所以要我们自己在子线程中创建一个使用主线程的Looper和MessageQueue的handler发送消息),如下图:

三、Message

在整个消息处理机制中,message又叫task,封装了任务携带的信息和处理该任务的handler。

1.尽管Message有public的默认构造方法,但是你应该通过Message.obtain()来从消息池中获得空消息对象,以节省资源。

2.如果你的message只需要携带简单的int信息,请优先使用Message.arg1和Message.arg2来传递信息,这比用Bundle更省内存

3.擅用message.what来标识信息,以便用不同方式处理message。

android基础(六)android的消息处理机制的更多相关文章

  1. <Android基础> (六) 数据存储 Part 1 文件存储方式

    第六章 数据存储 6.1 持久化技术 持久化技术指将内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失. 主要有三种方式用于简单地实现数据持久化功能:文件存储.S ...

  2. Android 基础 十一 Android的消息机制

    Handler是Android消息机制的上层接口,这使得在开发应用过程中我们只需要和Handler交互即可.Handler的使用过程很简单,通过它可以轻松地将一个任务切换到Handler所在的线程中去 ...

  3. <Android基础> (六) 数据存储 Part 3 SQLite数据库存储

    6.4 SQLite数据库存储 SQLite是一种轻量级的关系型数据库,运算速度快,占用资源少. 6.4.1 创建数据库 Android为了管理数据库,专门提供了SQLiteOpenHelper帮助类 ...

  4. <Android基础> (六) 数据存储 Part 2 SharedPreferences方式

    6.3 SharedPreferences存储 SharedPreferences使用键值对的方式来存储数据.同时支持多种不同的数据类型. 6.3.1 将数据存储到SharedPreferences中 ...

  5. [Android基础]Android中使用HttpURLConnection

    HttpURLConnection继承了URLConnection,因此也能够向指定站点发送GET请求.POST请求.它在URLConnetion的基础上提供了例如以下便捷的方法. int getRe ...

  6. 【Android 基础】Android中全屏或者取消标题栏

    先介绍去掉标题栏的方法: 第一种:也一般入门的时候经常使用的一种方法 requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏 注意这句一定要写在se ...

  7. Android(十六 ) android 与蓝牙串口通讯

    1.得到蓝牙适配器 BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 2.打开蓝牙 if (!mBl ...

  8. Android线程与异步消息处理机制

    在程序开发时,对于一些比较耗时的操作,我们通常会为其开辟一个单独的线程来执行,这样可以尽可能的减少用户等待的时间.在Android中,默认情况下,所有的操作都是在主线程中进行的,这个主线程负责管理与U ...

  9. 7.1 基础知识Android消息处理机制

    1. Android消息处理机制: Handler, MessageQueue, Looper, Thread 线程概念 : 一个应用程序运行时它的主体被称为进程, 一个进程内部可以有多个线程, 线程 ...

随机推荐

  1. for循环立即执行和不立即执行,js闭包

    <script type="text/javascript" src="jquery-2.1.1.min.js"></script> & ...

  2. 【LeetCode】#7 Reverse Integer

    [Question] Reverse digits of an integer. Example: x = 123, return 321 x = -123, return -321 [My Solu ...

  3. ajax向后台传递数组

    $.ajax({ traditional: true//这个设置为true,data:{"steps":["qwe","asd"," ...

  4. JavaScript中的splice方法

    splice方法根据传入的不同参数可分别实现删除和插入操作 使用splice(pra1,pra2,pra3)方法,需要为其提供如下参数: 1.pra1为其起始索引(即希望开始添加元素的地方) 2.pr ...

  5. 建站随手记:installation python virtualenv mezzanine -1

    aliyun的网络访问有时会有问题,pip有问题的时候使用豆瓣源 pip install $apptoinstall$ -i http://pypi.douban.com/simple ------- ...

  6. SAP验证

    需求:财务录费用凭证,检查科目6601001-6601999 & 成本中心为1000R001 - 1000R999,工单不能为空 GGB0 1.选择财务凭证->行项目->新建确认' ...

  7. css3放大效果

    参考案例: http://www.web-designers.cn/ http://www.harmay.com/ 鼠标经过图片,图片放大. 1.html: <body> <div& ...

  8. 不同json如何使用jsonArray以及ajax如何取,实现读取新闻

    jsp界面 <%@ page contentType="text/html;charset=gb2312"%><%@page import="org.j ...

  9. Jquery基础之DOM操作

    转自:http://www.cnblogs.com/bro-ma/p/3063942.html JQuery中的DOM操作主要对包括:建[新建].增[添加].删[删除].改[修改].查[查找][像数据 ...

  10. SQL Server数据库性能优化之SQL语句篇【转】

    SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...