Android源码分析--Handler和Looper机制详解
来源:互联网 发布:linux lamp一键安装 编辑:程序博客网 时间:2024/04/27 23:00
转自:http://blog.csdn.net/smbroe/article/details/44239961
在Android系统中的应用程序,与Java的应用程序相同,都是靠消息驱动,简单的说就是:有一个消息队列,我们可以不断的向这个消息队列中添加消息,并从中取出消息,处理消息。Android中与此工作相关的主要是由Handler,Looper以及Message来完成。
- Looper类:为一个线程运行着一个消息循环,内部有一个消息队列,每一个线程只允许最多存在一个Looper;
- Handler类:允许你向一个线程的消息队列中发送消息,处理消息;
- Message类:消息类。
使用样例
首先,我们通过一个简单的例子来学习如何使用,Looper和Handler,并通过这个例子来研究一下其工作原理;
1.我们在LooperThread中为消息循环做准备,并创建一个Handler用于处理消息,注意Handler的创建要在调用Looper.prepare()之后;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
2.接下来我们在主线程中创建一个新的线程,并通过LooperThread中的Handler向LooperThread线程发送消息;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
该例子主要是新创建一个Thread,并在该线程中向LooperThread发送消息。为了防止在发送消息时Handler还没建立,进行了同步,在mHandler为null时,阻塞该线程以等待,当建立了Handler后唤醒该线程。可以在log中看到结果:
Looper分析
由上面的例子我们可以看到如果我们想在本线程中进行消息管理,首先需要调用Looper.prepare方法,那就让我们一起首先来看一下这个方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
可以看到在prepare方法中首先判断了该线程中是否已经创建了Looper,接着调用了ThreadLocal的set方法。ThreadLocal是Java中的线程局部变量类,它使得各线程能够保持各自独立的一个对象,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。对于ThreadLocal机制在这里不做过多赘述。
在这里我们为该线程set了一个Looper,接下来然我们看看Looper的构造函数:
- 1
- 2
- 3
- 4
可以看到,在构造方法中,我们创建了一个新的消息队列并设置了当前的线程。
接下来我们创建了一个Handler,关于Handler我们一会了分析,在最后我们调用了Looper的loop方法用来进行消息循环。让我们来看看这个方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
可以看到,loop方法主要是从消息队列中不断的取出消息,并将该消息分发出去。
总结一下,Looper的工作:
- 封装了一个消息队列,
- 利用prepare将Looper和调用prepare方法的线程联系起来
- 利用loop函数分发消息
Handler分析
知道了Looper的工作,让我们来看看如何把消息发送出去。首先来看看它的构造方法,
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
无参数的构造方法调用了this(null, flase)构造方法,可以看到,在在Handler的成员变量中有一个Looper,首先获取了当前创建Handler的线程的Looper,另外可以看到在Handler中也保存了一个消息队列最终指向了Looper的消息队列。
当我们调用了sendMessage方法之后就向Looper发送了一条消息,让我们看看这个方法,消息是如何被传递的。sendMessage方法最终会调用到sendMessageAtTime方法来:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
可以看到,sendMessage方法最终调用了queue.enqueueMessage方法将消息加入到了Looper中的消息队列。
在上面我们看到了我们分发消息是调用了dispatchMessage方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
可以看到,dispatchMessage设置了一套消息处理的优先机制:
- 如果Message自带了Callback,则交给Message的Callback处理;
- 如果Handler了设置了Callback,则交给Handler的Callback处理;
- 如果两者都没有,则调用handleMessage方法处理。
Handler和Looper的同步问题
在上面的例子中我们可以发现,Handler和Looper是存在同步问题的,如果在LooperThread中Handler还没创建起来,在第二个线程中就发送了消息,这样就会引发空指针异常。在上面,我参考了Android中的HandlerThread,利用了wait/notifyAll的方法解决了这个问题,在实际使用时我们完全可以使用HandlerThread来完成。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
我们可以来看一下HandlerThread的源码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
可以看到,这个的思想和我们刚刚例子中所用的是一致的。
- Android源码分析--Handler和Looper机制详解
- Android源码分析--Handler和Looper机制详解
- Android源码分析--Handler和Looper机制详解
- Android应用程序消息处理机制(Looper、Handler)源码分析
- Android从源码分析一:Looper,Handler消息机制
- Android 消息机制 - Handler, Looper, Message, MessageQueue 的源码分析
- Android消息机制(Handler,Looper,MessageQueue)-源码分析
- handler ,Looper的机制,分析源码。
- Android的Looper和Handler消息处理机制详解
- Android的Looper和Handler消息处理机制详解
- Android的Looper和Handler消息处理机制详解
- Android Looper和Handler分析
- Android Looper和Handler分析
- Android Looper和Handler分析
- Android Looper和Handler分析
- Android Looper和Handler分析
- Android Looper和Handler分析
- Android Looper和Handler分析 .
- 【Python小项目】名片管理系统—函数升级版
- Tomcat 之 Session的活化和钝化 源码分析
- Mac 下android studio 快捷键
- 机器学习分类篇-最邻近规则分类KNN
- js中深拷贝与浅拷贝的区别
- Android源码分析--Handler和Looper机制详解
- 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
- 可重入锁 -- ReentrantLock
- 【C++错误处理】no matching function for call to transform
- 继承关系中子类与父类加载与初始化
- 回顾大一·C语言编程4.1(1)
- 如何通过dba_hist_active_sess_history分析数据库历史性能问题
- 编码规范
- CS R20 C(贪心+二分) D(套路(n后第k个合法数)二分+数位DP.) E(好题:回文,字符串哈希)