Looper、Message、Handler和HandlerThread之间的关系

Android中,使用AsyncTask来执行简单的后台线程,但是AsyncTask较适用于短暂的、不重复的运行任务。因为从Android3.2起,AsyncTask不再为每个实例创建线程,而是利用一个Executor在单一的后台线程上运行所有的AsyncTask后台任务,相当于所有的AsyncTask实例在同一个队列中排队运行,所以长时间且重复运行的AsyncTask会影响其他实例的运行,导致堵塞。实现按需下载的等后台运行方式,通常会使用到HandlerThread。

 

消息

首先介绍一下消息(Message),消息是Message类的实例,携带着需要处理的各种任务信息。有以下几个常见变量:

 

  1. what:用户定义的int型消息代码,用来描述和识别信息;
  2. obj:随消息发送的用户指定对象;
  3. target:处理消息的Handler,创建Message时会自动与一个Handler关联,通常不用手动设置;
  4. arg1、arg2:随消息返回的两个int类型参数。

 

Handler

Handler作为Message的目标,除了用来触发message的处理事件,也是创建和发布Message的接口。message是在Handler.handleMessage(...)方法中进行处理的。

 

Looper和Message、Handler的关系

Android的消息循环(message loop)由线程和looper组成。Looper对象管理着消息队列(meesage queue),消息队列中存放着许多的消息(message),它们与handler相关联。为了与Looper协同工作,Handler总是引用着Looper。主进程本身就是一个拥有handler和Looper的消息循环,在主线程中Android 默认已经调用了Looper.prepare()方法,调用该方法的目的是在Looper 中创建MessageQueue成员变量并把Looper对象绑定到当前线程中。

  • 一个Message只和一个目标Handler相关联,但是多个Message能引用同一个目标Handler。(如下图左)
  • 一个Handler只和一个Looper相关联,但是多个Handler可以与一个Looper相关联。所以消息队列中可能存放着来自不同Handler的Message。(如下图右)

          

 

创建Message并关联Handler

如果有一个类继承了HandlerThread,那么Handler可以在函数onLooperPrepared()中新建,因为该函数是在Looper首次检查消息队列之前调用的。一般会在new一个Handler的同时覆写其handleMessage(...)方法。

Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                //TODO
            }
        }
    };

 

消息的发送可以有以下几种:

 

  • 使用Handler.obtainMessage(...)方法来创建信息,此时可以将消息自动设置目标为该Handler对象,取得Message之后可以使用sendToTarget发送给Handler。Handler会把该Message放置在MessageQueue消息队列尾部
Message mMessage = mHandler.obtainMessage(...);
mMessage.sendToTarget();

 

  • 使用Handler.sendMessage(...)方法:
mHandler.sendMessage(message);

 

  • 也可以使用Handler.post()方式来发送消息:
mHandler.post(new Runnable() {
            @Override
            public void run() {
                //TODO
            }
        });

看看源码会发现它是把Runnable转换成了一条空的message,设置它的私有变量callback为我们传入的Runnable,然后再调用sendMessageDelayed(...)方法的。

当message设有回调方法时,它从消息队列取出后,是不会发给target Handler的,而是直接执行存储在callback中的Runnable的run()方法。
 

 

          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值