一、Looper

Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message。

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

1.Looper的成员变量:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; //一个MQ
final Thread mThread; //一个thread

Looper的代码是非常简单的。在官方文档的注释中,它推荐我们这样来使用它:

class LooperThread extends Thread {
public Handler mHandler; public void run() {
Looper.prepare(); mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
}; Looper.loop();
}
}

先看看prepare方法。

Looper.prepare

public static void prepare() {
prepare(true);
} private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//每个线程只能有一个looper
throw new RuntimeException("Only one Looper may be created per thread");
}
//设置本线程的looper。
sThreadLocal.set(new Looper(quitAllowed));
}

  注意prepare(boolean)方法中,有一个sThreadLocal变量(ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本),这个变量有点像一个哈希表,它的key是当前的线程,也就是说,它可以存储一些数据/引用,这些数据/引用是与当前线程是一一对应的,在这里的作用是,它判断一下当前线程是否有Looper这个对象,如果有,那么就报错了,"Only one Looper may be created per thread",一个线程只允许创建一个Looper,如果没有,就new一个。然后它调用了Looper的构造方法。

Looper 的构造方法

在上边调用了构造方法:Looper(quitAllowed),初始化了messageQueue并绑定当前线程。

private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

此时的初始化动作已经结束了,接下来看Looper.loop():

public static void loop() {
final Looper me = myLooper();//返回当前的looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;//取得messageQueue for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
。。。。
msg.target.dispatchMessage(msg);
。。。
msg.recycleUnchecked();
}
}

loop()方法,省去了一些不关心的部分。剩下的部分非常的清楚了,首先调用了静态方法myLooper()获取当前Looper对象。没有looper则抛出异常。

public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}

1. myLooper()同样是静态方法,它是直接从这个ThreadLocal中去获取Looper对象,拿到当前线程的Looper后;

2. MessageQueue queue = me.mQueue;拿到与这个Looper对应的MQ,就开始无限循环,不断的从消息队列中取出Message,当获取到一个消息后,它调用了Message.target.dispatchMessage()方法来对消息进行处理。dispatchMessage这个方法在Handler中,就是处理message。

3.msg.recycleUnchecked(),当这个msg处理完了,就没有用啦,把它回收到全局池中,注意不是销毁。

总结

Looper的代码看完了,我们得到了几个信息:

  • Looper调用静态方法prepare()来进行初始化,一个线程只能创建一个与之对应的LooperLooper初始化的时候会创建一个MQ,并和当前线程绑定,因此,有了这样的对应关系,一个线程对应一个Looper,一个Looper对应一个MQ。

  • Looper调用静态方法loop()开始无限循环的取消息,messageQueue调用next()方法来获取消息(这也是个无限循环)。

MessageQueue源码解析:http://www.cnblogs.com/jycboy/p/5786682.html

Handler源码解析:http://www.cnblogs.com/jycboy/p/5791457.html

Message源码解析:http://www.cnblogs.com/jycboy/p/5786551.html

Android Handler机制(三)----Looper源码解析的更多相关文章

  1. Android Handler机制(二)---MessageQueue源码解析

    MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...

  2. Handler机制原理图、源码、使用!!!!!

    android的消息处理机制——Looper,Handler,Message  (原理图.源码) 转自:http://my.oschina.net/u/1391648/blog/282892 在开始讨 ...

  3. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  4. 【Android应用开发】EasyDialog 源码解析

    示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...

  5. ThreadPoolExecutor系列三——ThreadPoolExecutor 源码解析

    ThreadPoolExecutor 源码解析 本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7681826.htm ...

  6. Handler Looper源码解析(Android消息传递机制)

    Android的Handler类应该是常用到的,多用于线程间的通信,以及子线程发送消息通知UI线程刷新View等等.这里我主要总结下我对整个消息传递机制,包括Handler,Looper,Messag ...

  7. Android 手势识别类 ( 三 ) GestureDetector 源码浅析

    前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...

  8. Android HandlerThread使用介绍以及源码解析

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例              HandlerThread是什么鬼?其本质就是一个线程,但是Han ...

  9. 多线程与高并发(三)—— 源码解析 AQS 原理

    一.前言 AQS 是一个同步框架,关于同步在操作系统(一)-- 进程同步 中对进程同步做了些概念性的介绍,我们了解到进程(线程同理,本文基于 JVM 讲解,故下文只称线程)同步的工具有很多:Mutex ...

随机推荐

  1. tomcat组成及工作原理

    1 - Tomcat Server的组成部分 1.1 - Server A Server element represents the entire Catalina servlet containe ...

  2. C# 读写App.config配置文件的方法

    我们经常会希望在程序中写入一些配置信息,例如版本号,以及数据库的连接字符串等.你可能知道在WinForm应用程序中可以利用Properties.Settings来进行类似的工作,但这些其实都利用了Ap ...

  3. Mac下github项目检出与提交

    项目检出 如果你的git还没有代码仓库,可以用过git的代码仓库页面新建一个你的仓库 创建git上的仓库后,我们还需要建立本地的仓库,所以打开Mac终端,建立本地仓库文件夹(这里我用HelloC),然 ...

  4. 基于MVC4+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出

    数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,我曾经在之前的一篇文章<Winform开发框架之通用数据导入导出操作>介绍了在Winform ...

  5. CentOS 配置防火墙操作实例(启、停、开、闭端口)

    防火墙的基本操作命令 查询防火墙状态:[root@localhost ~]# service   iptables status<回车> 停止防火墙:[root@localhost ~]# ...

  6. ajaxfileupload asp.net 的简单使用

    本人菜鸟,第一次写博客,不会排版,只是记录工作中常用的东西 ajaxfileupload.js源码: http://www.rczjp.cn/HTML/110420/20113620053635.ht ...

  7. Yii2框架打包成Phar包报错的经历

    以yii2为例 打包文件过程比较简单,但打包好以后简单测试yii命令,一直报错: PHP Fatal error: Uncaught yii\base\InvalidParamException: T ...

  8. Yii2.0学习笔记:第一个页面Saying Hello

    Controller目录下创建TestController.php 复制下面代码,yii跟tp一样,全程命名空间 <?php namespace app\controllers; use yii ...

  9. Guava学习笔记:Range

    在Guava中新增了一个新的类型Range,从名字就可以了解到,这个是和区间有关的数据结构.从Google官方文档可以得到定义:Range定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(C ...

  10. jquery刷新页面

    下面介绍全页面刷新方法:有时候可能会用到 window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.loc ...