Android Handler机制(三)----Looper源码解析
一、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()来进行初始化,一个线程只能创建一个与之对应的Looper,Looper初始化的时候会创建一个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源码解析的更多相关文章
- Android Handler机制(二)---MessageQueue源码解析
MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...
- Handler机制原理图、源码、使用!!!!!
android的消息处理机制——Looper,Handler,Message (原理图.源码) 转自:http://my.oschina.net/u/1391648/blog/282892 在开始讨 ...
- Android IntentService使用介绍以及源码解析
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...
- 【Android应用开发】EasyDialog 源码解析
示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...
- ThreadPoolExecutor系列三——ThreadPoolExecutor 源码解析
ThreadPoolExecutor 源码解析 本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7681826.htm ...
- Handler Looper源码解析(Android消息传递机制)
Android的Handler类应该是常用到的,多用于线程间的通信,以及子线程发送消息通知UI线程刷新View等等.这里我主要总结下我对整个消息传递机制,包括Handler,Looper,Messag ...
- Android 手势识别类 ( 三 ) GestureDetector 源码浅析
前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...
- Android HandlerThread使用介绍以及源码解析
摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例 HandlerThread是什么鬼?其本质就是一个线程,但是Han ...
- 多线程与高并发(三)—— 源码解析 AQS 原理
一.前言 AQS 是一个同步框架,关于同步在操作系统(一)-- 进程同步 中对进程同步做了些概念性的介绍,我们了解到进程(线程同理,本文基于 JVM 讲解,故下文只称线程)同步的工具有很多:Mutex ...
随机推荐
- tomcat组成及工作原理
1 - Tomcat Server的组成部分 1.1 - Server A Server element represents the entire Catalina servlet containe ...
- C# 读写App.config配置文件的方法
我们经常会希望在程序中写入一些配置信息,例如版本号,以及数据库的连接字符串等.你可能知道在WinForm应用程序中可以利用Properties.Settings来进行类似的工作,但这些其实都利用了Ap ...
- Mac下github项目检出与提交
项目检出 如果你的git还没有代码仓库,可以用过git的代码仓库页面新建一个你的仓库 创建git上的仓库后,我们还需要建立本地的仓库,所以打开Mac终端,建立本地仓库文件夹(这里我用HelloC),然 ...
- 基于MVC4+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出
数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,我曾经在之前的一篇文章<Winform开发框架之通用数据导入导出操作>介绍了在Winform ...
- CentOS 配置防火墙操作实例(启、停、开、闭端口)
防火墙的基本操作命令 查询防火墙状态:[root@localhost ~]# service iptables status<回车> 停止防火墙:[root@localhost ~]# ...
- ajaxfileupload asp.net 的简单使用
本人菜鸟,第一次写博客,不会排版,只是记录工作中常用的东西 ajaxfileupload.js源码: http://www.rczjp.cn/HTML/110420/20113620053635.ht ...
- Yii2框架打包成Phar包报错的经历
以yii2为例 打包文件过程比较简单,但打包好以后简单测试yii命令,一直报错: PHP Fatal error: Uncaught yii\base\InvalidParamException: T ...
- Yii2.0学习笔记:第一个页面Saying Hello
Controller目录下创建TestController.php 复制下面代码,yii跟tp一样,全程命名空间 <?php namespace app\controllers; use yii ...
- Guava学习笔记:Range
在Guava中新增了一个新的类型Range,从名字就可以了解到,这个是和区间有关的数据结构.从Google官方文档可以得到定义:Range定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(C ...
- jquery刷新页面
下面介绍全页面刷新方法:有时候可能会用到 window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.loc ...