Android Handler体系部分源码学习
2016-09-06 20:07
316 查看
先来看一下Handler的基本流程:
(1)先分析第一部分的代码 Looper.prepare():
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
可以看到就是创建一个Looper对象,然后存入ThreadLocal对象中,同时也就实现了每个线程都有相互独立Looper
(2)Looper.loop()
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
loop();开始调用以后就进入了死循环
并且不断获取下一个Message,
再将Message交给它的target的dispatchMessage方法进行处理。
(3)new Handler()
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
我们来看看 new Handler()到底做了什么,
其实就是获得当前线程的Looper,使得Handler与Looper进行绑定,这是默认的实现。
同时也有带有Looper的构造函数,这就代表了Handler其实可以绑定其他线程的Looper。
(4)post消息
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) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
可以看到在Handler中最终调用的就是将消息放入消息队列的方法
queue.enqueueMessage(msg, uptimeMillis);
总结:
最后,通过简单的学习几个相关类的源码,我们就可以试着理解为什么平时我们可以用Handler来解决子线程里更新UI的问题了:
(1)首先我们在主线程中 newHandler 绑定到了主线程中的Looper
(2)post出去的消息也就发到了UI线程中Looper的消息队列中
(3)Looper循环处理Message中的消息其实是回调了 Handler中的处理方法
(4)同时Looper是在它绑定的的线程里执行处理方法的,其实就相当于在UI线程中执行了处理代码,也就可以更新UI了。
这样Handler的原理是基本打通了,但是有很多细节还没能深入学习,一部分是因为再往下层涉及到的东西我还没看懂,估计还需要一段时间,所以先把阶段性的成果先放出来
(1)先分析第一部分的代码 Looper.prepare():
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
可以看到就是创建一个Looper对象,然后存入ThreadLocal对象中,同时也就实现了每个线程都有相互独立Looper
(2)Looper.loop()
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
loop();开始调用以后就进入了死循环
并且不断获取下一个Message,
再将Message交给它的target的dispatchMessage方法进行处理。
(3)new Handler()
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
我们来看看 new Handler()到底做了什么,
其实就是获得当前线程的Looper,使得Handler与Looper进行绑定,这是默认的实现。
同时也有带有Looper的构造函数,这就代表了Handler其实可以绑定其他线程的Looper。
(4)post消息
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) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
可以看到在Handler中最终调用的就是将消息放入消息队列的方法
queue.enqueueMessage(msg, uptimeMillis);
总结:
最后,通过简单的学习几个相关类的源码,我们就可以试着理解为什么平时我们可以用Handler来解决子线程里更新UI的问题了:
(1)首先我们在主线程中 newHandler 绑定到了主线程中的Looper
(2)post出去的消息也就发到了UI线程中Looper的消息队列中
(3)Looper循环处理Message中的消息其实是回调了 Handler中的处理方法
(4)同时Looper是在它绑定的的线程里执行处理方法的,其实就相当于在UI线程中执行了处理代码,也就可以更新UI了。
这样Handler的原理是基本打通了,但是有很多细节还没能深入学习,一部分是因为再往下层涉及到的东西我还没看懂,估计还需要一段时间,所以先把阶段性的成果先放出来
相关文章推荐
- Android多线程消息处理机制(三) Handler部分源码分析
- Android源码学习(1) Handler
- android 消息系统Handler、MessageQueue、Looper源码学习
- 学习嵌入式开发板的Android平台体系结构和源码结构
- Android源码学习(3) Handler之MessageQueue
- Android学习心得(24) --- Android Handler消息机制源码分析
- Android Study Material Design 六 之:TextInputLayout学习及分析部分源码
- Android源码学习(2) Handler之Looper
- Android源码学习(4) Handler之ThreadLocal
- Android Handler消息机制源码分析——第二部分: Message与Handler
- Android开发学习之路-Handler消息派发机制源码分析
- 新手学习android源码(一) 学习Handler,Looper,MessageQueue
- android消息处理机制学习(三)-Handler,Message,MessageQueue,Looper源码分析
- Android源码学习之三-Activity是如何进行自动化测试的
- Android2.1消息应用(Messaging)源码学习笔记(转载)
- 通过创建一个位图的XY Chart来学习Android绘图类Rect,Paint,Bitmap,Canvas(附源码)
- chrome源码学习之知识体系指南
- Android源码学习之七—传感器的背后
- DirectShow 学习(一) COM实现部分和部分辅助源码浅读
- Android源码学习之八—系统启动过程