首先来点基础描述:
主线程的handler的looper,也就是Loop.getMainLooper()
返回的loop,默认在ActivityThread
类的main
方法初始化了 ,在main方法里面调用了Loop.perpareMainLoper();
初始化了一个loop,所以一般主线程的looper
实际上就是那里初始化的looper具体
ActivityThread类的
main```代码如下:
public static void main(String[] args) {
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
创建了一个默认的loop又维护了一个messageQuare
主线程的looper轮训方法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;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
}
msg.recycleUnchecked();
}
}
那么handler类里面的dispatchMessage
触发是因为添加到消息队列中的消息Message
类的``target被设置了handler,然后在
Looper类的
loop方法里面处理这个消息的时候触发,也就是下面的这句代码
msg.target.dispatchMessage(msg);```
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.target.
的成员变量为handler,也就是代码是从这里调用的。
Looper相关方法
构建loop静态对象 保证一个线程只有一个
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
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.loop()
方法上面已经贴过了,也就是开启轮训,当没有的时候cpu进入等待。这个和某个酷Q机器人易语言源码当中的消息处理惊人的相似。他那个差不多就是消息队列的死循环,没有的时候就进行睡眠,然后有消息的时候线程唤醒。
里面用到了ThreadLocal
通过线程名作为键,保证了一个线程只有一个ThreadLocal
一个Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
ThreadLocal的关键方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
源码太深,这里只讲如何被设置上去的,
根据handler的源码分析,post
postDelay
实际上都最终调用了sendMessageAtTime
然后调用了
return enqueueMessage(queue, msg, uptimeMillis);
那么继续,先看看handler的一些方法,
public final Message obtainMessage()
{
return Message.obtain(this);
}
public final Message obtainMessage(int what)
{
return Message.obtain(this, what);
}
public final Message obtainMessage(int what, Object obj)
{
return Message.obtain(this, what, obj);
}
这里都把handler
传递进去了
Message
的obtain方法设置了 m.target
public static Message obtain(Handler h, int what, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.obj = obj;
return m;
}
既然是这样的,那么自己创建一个纯message类会触发吗?
Message message=new Message();
message.what=1;
message.obj="测试纯message";
handler.sendMessage(message);
结果令人震惊,还是触发了,这message.taget
他是如何被设置的呢?
然后又看了看,原来那报错的红色代码没有被我注意到,也就是说追踪走的sendMessageAtTime
方法走的enqueueMessage
方法中强制给message的targer设置了handler为自己。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
这句话明显的写这句话msg.target = this;
所以 明白为什么可以回调了,ok讲解完毕,知其然也知其所以然了。
其它相关
1、handler
类的queue
成员变量是从Looper中获取到的,handler发消息实际上是拿到Looper
里面的静态消息队列字段
mLooper.mQueue
2、而mQueue = new MessageQueue(quitAllowed);
也就是消息队列对象的初始化是通过prepare
的调用导致sThreadLocal.set(new Looper(quitAllowed));
这句代码被执行,然后导致Looper
构造方法执行,然后触发这个队列的初始化。···mQueue = new MessageQueue(quitAllowed);
···
sThreadLocal
也就是ThreadLocal
默认在成员变量就初始化了sThreadLocal
而且是静态的 这个字段也是放到Looper
类里面存起来的
3、真正负责处理消息的是在looper()
开启一个死循环for,不断的0调用MessageQueue
的next()
知道返回null才终止,,在这个方法几乎是没法出来了,永远卡在这个方法,除非满足特定条件,`比如messagequare
的quit
方法被调用。
4、looper
的looper
死死循环外,消息队列MessageQueue
next
也嵌套了一个死循环,所以即使消息没有也不会进行立马返回,而是等待,只有当有消息的时候才返回给looper()
处理这里面主要做一些时间的处理,比如那些延时时间发送的。
有些东西还是没法理解,深度对我来说还是遥不可及