您的位置:首页 > 产品设计 > UI/UE

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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息