Handler、Message、MessageQueue、 Looper、Handler Thread
2016-03-17 18:21
549 查看
简述:
在Android中,我们必须在主线程中更新UI,若在子线程中更新UI或者主线程中完成耗时的工作,就会出现异常。面对这种情况,我们可以使用Handler、Message、MessageQueue、 Looper组成的异步消息处理机制解决。在这个机制中主要用到了消息循环(message loop)的结构。
通俗例子:
想象应用是一间商店,闪电侠是员工(犹如应用里的线程),闪电侠可能要负责招待客户、布置商品、联系调货等工作。假如只有一个闪电侠,他要处理如打电话到其他店里调货的耗
4000
时任务,店里的顾客可能会等得不耐烦。
要想解决问题,需要再雇佣一名闪电侠专门负责调货的工作。 即创建一个后台线程,然后通过该线程完成耗时任务。
后台工作的闪电侠已结束调货任务。他需要将调货已完成的消息通知给前台工作的闪电侠。如果前台闪电侠非常忙碌,则后台闪电侠可能无法立即与他取得联系。
他可以选择等到前台闪电侠空闲时再联系。这虽然可行,但效率不高。
比较好的解决方案是为每个闪电侠提供一个收件箱。后台闪电侠写下调货已完成的信息,并将 其放置在前台闪电侠的收件箱顶部。而前台闪电侠如需告知后台闪电侠库存已空的信息,也可执行类似操作。
有时,闪电侠可能需要及时完成某项任务,但当时并不方 便去做。这种情况下,他也可以在自己的收件箱放上一条提醒消息,然后在空闲的时候去完成它。
结构图分析:
HandlerThread类是已经拥有Looper的方便Thread类。一般在onLooperPrepared()函数中写需要执行的内容。(普通线程是没有Looper的,直接new Handler会异常)
正常使用流程:
在带有Looper的线程中创建Handler对象,Handler对象内带有该Looper的引用。Handler调用方法发送Message对象(本质通过Looper,因为MessageQueue其实在Looper内),Message对象会添加到MessageQueue中。
Looper会一直从MessageQueue中取出Message对象,最后分发回发送该Message对象的Handler的handlerMessage()方法中处理。
一个Handler仅与一个Looper相关联,多个Handler可与同一个Looper相关联。一个Message也仅与一个目标Handler相关联。 Looper拥有着整个Message队列。
Handler类:
Handler用于发送(sendMessage()方法)和处理Message(handleMessage()方法)。Handler允许你发送和处理与线程对应MessageQueue相关联的Message对象和Runnable对象。每一个Handler实例与只与一个线程和该线程的MessageQueue相关联。当你创建一个新的Handler对象时,它便与创建它的线程及MessageQueue绑定在一起。从那时候起,它会发送Message对象或Runnable对象到那个绑定了的MessageQueue处,然后当Message对象或Runnable对象从MessageQueue中被取出的时候,Handler会对它们进行处理。
Handler有两个主要用途:
1. 安排Message对象或Runnable对象在某个未来的时间点被处理。
2. 通过在其他线程中的MessageQueue中放入Message,使行为在其他线程中完成。
关键成员:
final MessageQueue mQueue;
final Looper mLooper;
关键方法:
obtainMessage() //从公共循环池里获取消息。比创建新实例有效率
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); // 最终调用了mQueue的enqueueMessage()方法 }
Message类:
Message类的对象可以在内部携带信息public int what; 用户定义的int型消息代码,用来描述消息;
public Object obj; 随消息发送的用户指定对象;
/package/ Handler target; 处理消息的Handler。
Message在创建时,会自动与一个Handler相关联。 Message在准备处理状态下, Handler是负责让消息处理行为发生的对象。
Looper类:
Looper是用来为一个Thread对象运行消息循环的。默认的线程是没有消息循环的。我们也可以为Thread创建一个Looper,在线程中调用Looper.prepare()来启动loop,然后调用loop()使之处理messages。class LooperThread extends Thread{ public Handler mHandler; publicvoid run(){ Looper.prepare(); mHandler =new Handler(){ publicvoid handleMessage(Message msg){ // process incoming messages here } }; Looper.loop(); } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories