学习并理解 handler,looper,message之间的关系
来源:互联网 发布:latex mac下载官网 编辑:程序博客网 时间:2024/05/16 17:31
学习并理解 handler,looper,message之间的关系
先看 Looper 源代码
private Looper() { **//3,创建Looper**// 创建一个新的消息队列 mQueue = new MessageQueue(); mRun = true;// 将创建的looper和当前线程绑定在一起 mThread = Thread.currentThread();}public static final void prepare() { //2,调用prepare()// 这个判断保证一个线程只能有一个looper if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); }// 创建一个looper存放在 ThreadLocal 中, ThreadLocal 的作用就是保证每个线程操作都是自己的对象 sThreadLocal.set(new Looper()); //3,创建Looper}public static final void prepareMainLooper() {// 1, 调用此方法创建 一个Looper prepare(); // 2,调用prepare() setMainLooper(myLooper()); if (Process.supportsProcesses()) { myLooper().mQueue.mQuitAllowed = false; }}public static final void loop() { // 4,loop方法// 获取之前放在 ThreadLocal 中创建的 Looper对象和消息队列 Looper me = myLooper(); MessageQueue queue = me.mQueue; ..... while (true) { // 代码执行到这里会阻塞。。。 这时候跳到 第二大步骤 Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } .... msg.target.dispatchMessage(msg); // 这个msg.target就是handler,用来区分不同的handler。 .... } }}public static final Looper myLooper() { return (Looper)sThreadLocal.get();}
一,首先一个程序的启动时,他的UI线程(也就是主线程)会在main 方法中调用 Looper的静态方法
# ActivityThread.java 主线程中的部分代码
public static final void main(String[] args) {
.....// 1, 调用此方法创建 一个Looper Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false);.....// 4,调用此死循环方法不断的从消息队列中读取消息。 Looper.loop();
}
二,关于handler,搞清楚前面的Looper 后 再来看看handler是怎么工作的
当我们在activity中创建handler写下下面代码时。
private Handler handler = new Handler() {
@Override public void handleMessage(Message msg) {}
}
来看看他的构造函数
public Handler() {
….
// 这里又调用到了Looper.myLooper()方法,这里得到了UI线程之前创建的Looper。
mLooper = Looper.myLooper();
….
// 此处获得UI线程创建的消息队列
mQueue = mLooper.mQueue;
mCallback = null;
}
可以看到通过Handler() 构造函数 ,新建的handler对象和Looper对象,消息队列绑定在一起了。
总结 一,二 两大步骤可以知道 一个线程里面只有一个looper 和messagequeue,我们有时在activity中却可以创建多个handler的对象发送
消息,那么looper是如何识别不同的handler对象呢,最后跳到第三大步,发送message。
三,我们一般都会开启一个子线程进行一些耗时操作,然后在子线程中发送消息到主线程,主线程在执行更新ui的操作。
当我们使用handler.sendMessage(msg)时,看看handler的源码
public void handleMessage(Message msg) {
}public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0);}public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; // 得到消息队列 MessageQueue queue = mQueue; if (queue != null) { // 将当前发送message的对象赋值给msg.target属性,这个属性就是用来区分不同的handler msg.target = this; // 调用messagequeue的方法 sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent;}
可以看到 最后调用sendMessageAtTime()这个方法,再来看看这个方法
得到消息队列
MessageQueue queue = mQueue;
if (queue != null) {
// 将当前发送message的对象赋值给msg.target属性,这个属性就是用来区分不同的handler
msg.target = this;
// 调用messagequeue的方法,
sent = queue.enqueueMessage(msg, uptimeMillis);
最后调用queue.enqueueMessage()方法,将消息添加到消息队列
来看看 MessageQueue.enqueueMessage 代码
final boolean enqueueMessage(Message msg, long when) { ... Message p = mMessages; if (p == null || when == 0 || when < p.when) { // 当前发送的message需要马上被处理调,needWake唤醒状态置true msg.next = p; mMessages = msg; needWake = mBlocked; // new head, might need to wake up } else { // 当前发送的message被排队到其他message的后面,needWake唤醒状态置false Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; needWake = false; // still waiting on head, no need to wake up } } // 是否唤醒主线程 if (needWake) { nativeWake(mPtr); } return true;
}
当handler.sendMessage(msg)完成后,之前的UI线程的loop方法中 Message msg = queue.next()就不会再阻塞了,会依次执行下去
当执行到 msg.target.dispatchMessage(msg);方法时。可以看到hanlder源码最终执行的是 handleMessage()。而我们新建的handler 又重
写了这个方法。从而在主线程进行一些ui操作。
小结下,总的来说就是ui线程会在程序启动时,创建looper和消息队列,然后调用Looper的静态方法 loop(),这个方法中 message msg =
queue.next();//如果里面没有消息就会阻塞。如果Handler在主线程中创建,Looper会在死循环里等待取消息,1、没取到,就阻塞,2、一
旦被子线程唤醒,取到消息,就把Message交给Handler处理。子线程用Handler去发送消息,拿写入描述符去写消息,唤醒主线程。
- 学习并理解 handler,looper,message之间的关系
- 学习Handler,Message,MessageQueue,Thread,Looper之间的关系
- Message、Handler、MessageQueue、Looper之间的关系
- Message,Handler,MessageQueue,Looper之间的关系
- Message、Handler、MessageQueue、Looper之间的关系
- Handler、looper、Message之间的关系?
- Handler 、 Looper 、Message之间的关系
- Message、Handler、Message Queue、Looper之间的关系
- Message、Handler、Message Queue、Looper之间的关系
- android 中Message、Handler、Message Queue、Looper之间的关系
- android 中Message、Handler、Message Queue、Looper之间的关系
- Message、Handler、Message Queue、Looper之间的关系
- Message、Handler、Message Queue、Looper之间的关系
- Message、Handler、Message Queue、Looper之间的关系。
- Handler 机制学习之Handler、Looper、MessageQueue、Message之间的关系
- Android 阅读源码,让你彻底理解Handler、Message、Looper之间的关系
- Android 深入理解Handler, Looper, Message 三者之间的关系
- Handler、HandlerThread、Message之间的关系理解
- poj 1410 Intersection 【判断线段 与矩形面是否相交】
- JAVA crawler
- (NO.00001)iOS游戏SpeedBoy Lite成形记(十二)
- username!= null 与 !"".equals(username)区别
- NASM在Ubuntu上的安装与简单使用
- 学习并理解 handler,looper,message之间的关系
- Caused by: android.content.res.Resources$NotFoundException: File res/drawable-mdpi/
- 从机器学习谈起
- webpy 入门
- 通过注释省略findviewbyid
- JavaScript函数基础
- cf 3a Shortest path of the king
- HDU1269:迷宫城堡【强连通】
- Hive简单介绍