Handler、Message、MessageQueue、Looper 理解

这几个东西,总是觉得熟悉又不熟悉,而且更感觉“像风像雨又像雾”,总是迷迷糊糊的。现在就拿出来单独看一下,它们到底是什么东西,当然,仅仅是自己工作中的一个理解加上源码分析。

先总的说一下对这几个东西关系,总的理解为就是Handler发送Message到MessageQueue通过Looper轮询取出Message再交由Handler处理。

首先说Handler,Handler在代码中使用最多的就是从子线程发消息通知主线程来更新UI,这是我们用到Handler最多的情况。因为安卓更新UI只能在ActivityThread(主线程)进行更新,而耗时的处理操作又不能放在主线程操作,因为,一用户体验不好,二是容易程序ANR(Application Not Respond)程序无响应,所以耗时操作我们通常开启新的线程来处理,处理完后通过Handler发送消息,然后重写Handler的handleMessage方法来更新UI。

从上面分析来理解我们可以分析出来,Handler主要处理两件事,一是发送消息,二是处理消息。
Handler发送消息,我们通常会有两个系列的方法Send和Post,主要区别是Send直接处理消息,而Post需要将一系列“零件”组装成消息再调用Send方法来发送。

先看Send方法:

Send方法

点击第一个方法,最终方法其会一层层调用不同的重载方法,最终调用:

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);
    }

这个方法的作用就是将一个消息压入MessageQueue,从其名称看,它是一个消息队列,既然是“队列”,那就会队列的基本常规操作:
1、新建队列
2、元素入队,上面的enqueueMessage(…)就是元素入队方法。
3、元素出队, Message next()方法。
4、删除元素, removeMessage( )方法。
5、销毁队列

再看Post方法:

Post方法:

随便查看一个方法

 public final boolean postAtTime(Runnable r, long uptimeMillis)
 {
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
 }

看以看到其调用了sendMessageAtTime()方法,其中第一个参数需要一个Message,这个Message就是利用参数r,通过getPostMessage(r)得到的,其最终也是将一个消息压入消息队列。

分析到这里,Handler把Message压入MessageQueue的过程已经结束,但Handler还有一个功能就是处理Message,那Message又是怎么取出来,最终交由Handler处理的呢?Looper,就应该上场了,其单词本意有循环的意思,可以理解成发动机,它是整个消息轮询的动力来源。先不看这个类,先看上面的sendMessageAtTime消息入队列方法,这里面有一句MessageQueue queue = mQueue,通过代码追踪可以看到mQueue变量是通过new Handler()里的 mQueue = mLooper.mQueue;进行赋值的:

 public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

mLooper又是通过mLooper = Looper.myLooper()赋值的,也就是消息队列是围绕Looper展开的,现在再来看Lopper.myLooper()静态方法,它是通过sThreadLocal静态变量存储的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值