一、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. SQL中利用DMV进行数据库性能分析

    相信朋友对SQL Server性能调优相关的知识或多或少都有一些了解.虽然说现在NOSQL相关的技术非常的火热,但是RMDB(关系型数据库)与NOSQL是并存的,并且适用在各种的项目中.在一般的企业级 ...

  2. 第23/24周 临时数据库(TempDb)

    在今天的性能调优培训里我们讨论下TempDb——SQL Server的公共厕所,在SQL Server里我是这样描述它的.我们的每个人都会经常使用TempDb.有些人直接使用它,有些人不直接使用它.今 ...

  3. CSS易混淆知识点总结与分享-定位与布局

    CSS定位有四种模式:static.relative.absolute.fixed,其它static是默认值,下面分别讲解下各自的特点: static:静态定位,处于动态布局流中,按照页面中的各元素先 ...

  4. 驱动开发利器Microsoft Windows Driver Kit 7.1.0下载

    在Windows 2000 与Windows XP 系统采用是WINDDK来开发WINDOWS驱动程序,我手头也有WINDDK,可是从Windows Vista开始之后,一般采用Microsoft W ...

  5. C#中使用Sql对Excel条件查询

    如何在C#中实现对Excel的条件查询呢? 在使用Sql条件语句对Excel进行查询时,遇到"至少一个参数没有被指定值"的问题,如何解决? 使用OleDbConnection对象创 ...

  6. xamarin.ios 实现圆形进度条

    using System; using UIKit; using System.Drawing; using CoreAnimation; namespace PMM { public class P ...

  7. 修复 XE8 for Android 分享图片到 Gmail 权限不足的问题

    问题:打开 XE8 的 ShareSheet 示例,发布到 Android 实机,按 Share 选 Gmail 结果显示:没有权限添加附件. 适用:XE8 for Android 修复方法: 请将源 ...

  8. ThinkCMF变量输出+使用函数

    ThinkCMF变量输出+使用函数的方式同ThinkPHP. ThinkPHP变量输出: 在模板中输出变量的方法很简单,例如,在控制器中我们给模板变量赋值: $name = 'ThinkPHP'; $ ...

  9. [moka同学笔记]Yii2.0给一张表中增加一个属性

    1.model中建立关联 public function getUser(){ return$this->hasOne(User::className(),['id'=>'uid']) ; ...

  10. php学习5-时间和日期

    如果时间时区不对,使用时间是要先设定时区,使用date_default_timezone_set() 设置新时区 date_default_timezone_set('Asia/Shanghai'); ...