Handler机制.源码分析
2016-10-02 22:30
232 查看
Handler机制的原理 :Android提供了handler 和 looper 来满足线程之间的通信
Handler是先进先出的原则
一个线程可以产生一个looper对象,由它去管理线程里面消息队列 MessageQueue
Handler 你可以构造handler对象来与looper沟通.可以发送消息 和处理消息
MessageQueue 用来存放线程放入的消息
线程 一般值的是主线程 UIthread
Android启动程序的时候会替他建立一个MessageQueue
消息池
Handler发送消息
ThreadLocal
Handler 处理消息
andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message
Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建 消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃
圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用
ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的 Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
子线程通过Handler、Looper与UI主线程通信的流程如图所示。
相关的术语 :
通信的同步 Synchronous指向客户端发送请求后,必须要在服务端有回应后客户端才继续发送其它的请求,所以这时所有请求将会在服务端得到同步,直到服务端返回请求。
通信的异步 Asynchronous 指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求。
所谓同步调用,就是在一个函数或方法调用时,没有得到结果之前,该调用就不返回,直到返回 结果。异步调用和同步是相对的,在一个异步调用发起后,被调用者立即返回给调用者,但是调用者不能立刻得到结果,被调用都在实际处理这个调用的请求完成 后,通过状态、通知或回调等方式来通知调用者请求处理的结果。
Android的消息处理有三个核心的类
Looper handler 和 message 其实还有一个MessageQueue 但是它被封装在looper中,不会直接和它打交道,所以不算是核心的类.
消息类Message类 主要的功能是进行消息的封装,同时可以指定消息的操作形式
Int whatobject obj Handler getTraget
尽管message有默认的构造,但是我们应该是通过Message.ontain() 来从消息池中获取消息对象,节省资源
如果是只是简单地携带int信息,优先使用Message.arg1和Message.arg2来传递信息,这比Bundle更省内存
善用message.what
来标示信息,以便不同的方式来处理message
消息通道 looper 系统会自动创建looper对象,但是如果是用户自定义的一个类中,就需要手动的调用looper中的方法.才可以启动looper对象
表面的意思是循环者,它被设计一个普通的线程变成looper线程,所说的looper线程就是循环工作的线程
.looper.prepare() ; 处理其他,比如实例化handler
…… looper.loop()
一个线程只可以有一个looper对象,为什么???
看源码 ,可以看出创建looper对象其实就是将looper对象定义为ThreadLocal,如果这个对象以前定义了,妮又尝试着去重新的定义,就是说threaLocal.get()!=null
这个时候对象存在,就会爆异常 .
looper.loop() 这个代表着启动looper 线程开始工作了.它不断的从队列里面取出消息.每次去的是第一个消息.源码分析 :
调用这个方法后,内部的执行流程
1.获取当前线程的looper对象
2. 获取消息队列
3. 开启一个while死循环
用队列的对象取出下一个消息
如果不是空,将消息交给handler
looper中的其他的方法 myLooper() getThread()
quit() 结束looper的循环 public void quit()
综上,Looper有以下几个要点:
1)每个线程有且只能有一个Looper对象,它是一个ThreadLocal
2)Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3)Looper使一个线程变成Looper线程。
那么,我们如何操作Message Queue上的消息呢?这就是Handler的用处了
消息操作类 handler
处理消息,但是很小气,只处理自己发出的消息
默认关联当前线程的looper
mLooper = Looper.myLooper();判断looper是不是空的,如果是空的就爆异常,就是指handler只可以在looper线程中使用,关联looper的消息队列,因为他的消息要发送到looper的消息队列中public class LooperThread extends Thread { private Handler handler1; private Handler handler2; @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); // 实例化两个handler handler1 = new Handler(); handler2 = new Handler(); // 开始循环处理消息队列 Looper.loop(); }}一个线程可以有多个handler 但是只能有一个looper有了handler之后 就可以发送消息;了 post(Runnable) postAtTime(Runnable, long) postDelayed(Runnable, long) sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message, long)sendMessageDelayed(Message, long) post发送消息最后都是把里面的Runnable封装成了message // 此方法用于向关联的MQ上发送Runnable对象,它的run方法将在handler关联的looper线程中执行 public final boolean post(Runnable r) { // 注意getPostMessage(r)将runnable封装成message return sendMessageDelayed(getPostMessage(r), 0); } private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); //得到空的message m.callback = r; //将runnable设为message的callback, return m; } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; // message的target必须设为该handler! sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } 发送消息的时候 ,设置target为当前发送消息的handler,这样就可以方便的找到处理消息的handler对象
发送消息之后,是怎么处理消息的 dispathMessage(Message msg) 和 钩子方法 handleMessage(Message msg)dispatchMessage(Message msg) { (msg.callback != ) { handleCallback(msg); } { (mCallback != ) { (mCallback.handleMessage(msg)) { ; } } handleMessage(msg); } } handleCallback(Message message) { message.callback.run(); } handleMessage(Message msg) { }
来自为知笔记(Wiz)
Handler是先进先出的原则
一个线程可以产生一个looper对象,由它去管理线程里面消息队列 MessageQueue
Handler 你可以构造handler对象来与looper沟通.可以发送消息 和处理消息
MessageQueue 用来存放线程放入的消息
线程 一般值的是主线程 UIthread
Android启动程序的时候会替他建立一个MessageQueue
.Handler创建消息
消息池消息池
Handler发送消息
ThreadLocal
Handler 处理消息
andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message
Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建 消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃
圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用
ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的 Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
子线程通过Handler、Looper与UI主线程通信的流程如图所示。
相关的术语 :
通信的同步 Synchronous指向客户端发送请求后,必须要在服务端有回应后客户端才继续发送其它的请求,所以这时所有请求将会在服务端得到同步,直到服务端返回请求。
通信的异步 Asynchronous 指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求。
所谓同步调用,就是在一个函数或方法调用时,没有得到结果之前,该调用就不返回,直到返回 结果。异步调用和同步是相对的,在一个异步调用发起后,被调用者立即返回给调用者,但是调用者不能立刻得到结果,被调用都在实际处理这个调用的请求完成 后,通过状态、通知或回调等方式来通知调用者请求处理的结果。
Android的消息处理有三个核心的类
Looper handler 和 message 其实还有一个MessageQueue 但是它被封装在looper中,不会直接和它打交道,所以不算是核心的类.
消息类Message类 主要的功能是进行消息的封装,同时可以指定消息的操作形式
Int whatobject obj Handler getTraget
尽管message有默认的构造,但是我们应该是通过Message.ontain() 来从消息池中获取消息对象,节省资源
如果是只是简单地携带int信息,优先使用Message.arg1和Message.arg2来传递信息,这比Bundle更省内存
善用message.what
来标示信息,以便不同的方式来处理message
消息通道 looper 系统会自动创建looper对象,但是如果是用户自定义的一个类中,就需要手动的调用looper中的方法.才可以启动looper对象
表面的意思是循环者,它被设计一个普通的线程变成looper线程,所说的looper线程就是循环工作的线程
.looper.prepare() ; 处理其他,比如实例化handler
…… looper.loop()
一个线程只可以有一个looper对象,为什么???
public
class Looper
{
// 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
private
static
final
ThreadLocal sThreadLocal =new
ThreadLocal();
// Looper内的消息队列
final
MessageQueue mQueue;
// 当前线程
Thread mThread;
//其他属性
// 每个Looper对象中有它的消息队列,和它所属的线程
private Looper()
{
mQueue =new
MessageQueue();
mRun =true
;
mThread = Thread.currentThread();
}
// 我们调用该方法会在调用线程的TLS中创建Looper对象
public static final void prepare()
{
if
(sThreadLocal.get() !=null
) {
// 试图在有Looper的线程中再次创建Looper将抛出异常
throw
new
RuntimeException("Only one Looper may be created per thread"
);
}
sThreadLocal.set(new
Looper());
}
// 其他方法
}[/code]
看源码 ,可以看出创建looper对象其实就是将looper对象定义为ThreadLocal,如果这个对象以前定义了,妮又尝试着去重新的定义,就是说threaLocal.get()!=null
这个时候对象存在,就会爆异常 .
looper.loop() 这个代表着启动looper 线程开始工作了.它不断的从队列里面取出消息.每次去的是第一个消息.源码分析 :
调用这个方法后,内部的执行流程
1.获取当前线程的looper对象
Looper me = myLooper();这个方法内部其实就是返回 ThreadLocal.get()
2. 获取消息队列
MessageQueue queue = me.mQueue;
3. 开启一个while死循环
用队列的对象取出下一个消息
Message msg = queue.next
();判断消息是否为空,如果是空,就不会继续执行了
如果不是空,将消息交给handler
msg.target.dispatchMessage(msg);
msg.recycle();回收msg资源
looper中的其他的方法 myLooper() getThread()
quit() 结束looper的循环 public void quit()
{
// 创建一个空的message,它的target为NULL,表示结束循环消息
Message msg = Message.obtain();
// 发出消息
mQueue.enqueueMessage(msg,0
);
}[/code]
综上,Looper有以下几个要点:
1)每个线程有且只能有一个Looper对象,它是一个ThreadLocal
2)Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3)Looper使一个线程变成Looper线程。
那么,我们如何操作Message Queue上的消息呢?这就是Handler的用处了
消息操作类 handler
处理消息,但是很小气,只处理自己发出的消息
默认关联当前线程的looper
mLooper = Looper.myLooper();判断looper是不是空的,如果是空的就爆异常,就是指handler只可以在looper线程中使用,关联looper的消息队列,因为他的消息要发送到looper的消息队列中public class LooperThread extends Thread { private Handler handler1; private Handler handler2; @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); // 实例化两个handler handler1 = new Handler(); handler2 = new Handler(); // 开始循环处理消息队列 Looper.loop(); }}一个线程可以有多个handler 但是只能有一个looper有了handler之后 就可以发送消息;了 post(Runnable) postAtTime(Runnable, long) postDelayed(Runnable, long) sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message, long)sendMessageDelayed(Message, long) post发送消息最后都是把里面的Runnable封装成了message // 此方法用于向关联的MQ上发送Runnable对象,它的run方法将在handler关联的looper线程中执行 public final boolean post(Runnable r) { // 注意getPostMessage(r)将runnable封装成message return sendMessageDelayed(getPostMessage(r), 0); } private final Message getPostMessage(Runnable r) { Message m = Message.obtain(); //得到空的message m.callback = r; //将runnable设为message的callback, return m; } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; // message的target必须设为该handler! sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } 发送消息的时候 ,设置target为当前发送消息的handler,这样就可以方便的找到处理消息的handler对象
发送消息之后,是怎么处理消息的 dispathMessage(Message msg) 和 钩子方法 handleMessage(Message msg)dispatchMessage(Message msg) { (msg.callback != ) { handleCallback(msg); } { (mCallback != ) { (mCallback.handleMessage(msg)) { ; } } handleMessage(msg); } } handleCallback(Message message) { message.callback.run(); } handleMessage(Message msg) { }
来自为知笔记(Wiz)
相关文章推荐
- Handler机制-从源码角度分析
- Android源码分析笔记--Handler机制
- handler机制(二)源码分析
- Handler机制源码分析(异步一)
- Android源码分析--Handler机制的实现与工作原理
- 源码分析Handler机制
- android源码分析系列(一):Handler机制
- 从源码角度分析java层Handler机制
- Android Handler机制(一)---Message源码分析
- Handler机制流程梳理、源码分析
- Handler机制的源码分析
- 源码分析 — Handler机制(线程间通信)
- [置顶] Android源码分析——Looper,Messagequeue,Message,handler初始化及handler机制简介
- 通过源码分析Android Handler机制
- Android源码分析之Handler机制
- handler机制的源码分析
- handler机制 源码分析 梳理
- Android Handler机制源码分析
- JBPM源码分析(一)---数据库表主键ID的产生机制
- Struts-menu源码分析(转贴)