所要用到的android源码路径:
ActivityThread源码路径:android-4.0.3_r1\frameworks\base\core\java\android\app\ActivityThread
Activity源码路径:android-4.0.3_r1\frameworks\base\core\java\android\app\Activity
Handler源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Handler
Looper源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Looper
Message源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\Message
MessageQueue源码路径:android-4.0.3_r1\frameworks\base\core\java\android\os\MessageQueue
我们从使用handler发送一条message到接收进行处理的这个过程来理解Handler,Looper,MessageQueue的实现,在Activity主线程中,会默认
创建一个Looper对象,在这个Looper类中会创建一个MessageQueue的消息队列,然后主线程会调用Looper的的loop()方法循环遍历这个消息队
列,如果有消息则会通过Handler对象将消息传递到handlerMessage方法中进行处理,如果Hanlder对象为空也就是没有创建Hanlder对象则会将
这条消息丢掉。那么消息的发送是怎样的呢?我们创建一个Handler对象,使用这个对象发送Message,其实是使用Looper对象传递进来的
MessageQueue,通过这个消息队列的引用将Message放进消息队列中,由于Looper会遍历这个队列,所以Handler对象发送msg,将其放进消
息队列,Looper遍历消息队列将消息取出,然后传递给Hanlder进行处理,这样一个消息的发送与接收就完成了。
首先我们根据Handler的构造函数来了解Handler的几种使用方法,从API中我们知道Handler有四个构造函数,分别是:
Handler()
Handler(callback)
Handler(looper)
Handler(looper, callback)
一、不带参数的Handler()构造函数,其使用的是主线程默认的Looper对象以及MessageQueue
Handler handler2 = new Handler(){
public void handleMessage(Message msg) {
};
};
handler2.sendEmptyMessage(30);
直接在Activity中new一个Handler对象,并且重载handlerMessage方法就能够实现Message的发送与接收。
二、Handler(callback)构造函数,带了一个Hanlder类中的一个Callable接口对象作为参数,看源码就能够很清楚知道,他的作用其实是将handlerMessage
方法给独立出去,也就是在Activity中如果handlerMessage中的代码量太多,使用这个构造函数去创建对象,就能够将handlerMessage方法不放在
Activity中。
public class MyHandler implements Handler.Callback{
@Override
public boolean handleMessage(Message arg0) {
return false;
}
}
先实现Hanlder.Callback接口,丛杂handlerMessage方法,在这里进行消息的处理
MyHandler callback = new MyHandler();
Handler handler3 = new Handler(callback);
handler3.sendEmptyMessage(20);
在Activity中创建Handler对象,将Callback对象作为参数传递进去,然后使用handler发送Message,就能够在MyHandler中接收消息进行处理。
三、Handler(looper)构造函数,带了一个自定义的Looper对象作为参数,所以我们只要自定义一个Looper,然后将该Looper对象传递进去就能够正常
的进行消息发送与接收。但是我们不必要真的去自定义一个Looper类,我们只需要继承android已经实现好的HandlerThread线程,就能够自定义一个
Looper类
public class MyThread extends HandlerThread{
//HandlerThread类是android中已经继承Thread的类,他已经帮你实现了Looper对象的创建
//所以如果我们在实现Handler时,需要自定义Looper对象,则直接继承此类就行。
public MyThread(String name) {
super(name);
}
@Override
protected void onLooperPrepared() {
//这个方法是在Looper.loop()被调用前在线程HandlerThread的run方法中被调用
//所以如果要在这之前做什么操作,就需要重载这个方法
Log.i("MyThread", "onLooperPrepared");
super.onLooperPrepared();
}
}
MyThread thread = new MyThread("thread");
thread.start();
Looper looper = thread.getLooper();
Handler handler1 = new Handler(looper){
public void handleMessage(Message msg) {
}
};
handler1.sendEmptyMessage(10);
这样我们就能够使用自定义的Looper进行消息的发送与接收,而不必使用Activity帮我们已经创建好的默认的Looper对象。
四、Handler(looper, callback)构造函数,知道了前面三种构造函数之后,这种就能够很容易理解了:使用自定义Looper,将handlerMessage方法
从创建Handler对象的类中独立出去。
Handler的详细使用方法就介绍完了,接下来我们就来分析相关类的源码,来彻底了解其运作过程。
首先我们来看看Looper的实现过程,我们知道在创建一个Activity时,其主UI主线程ActivityThread中会默认创建一个Looper对象,那么这个对象是在
什么地方创建的呢?
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
step1:从上面ActivityThread源码中我们可以看见,这个main方法是主线程的启动的地方,首先他调用了Looper的静态prepareMainLooper()方法:
public static void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
myLooper().mQueue.mQuitAllowed = false;
}
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
private synchronized static void setMainLooper(Looper looper) {
mMainLooper = looper;
}
public static Looper myLooper() {
return sThreadLocal.get();
}
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
在上面源码中我们可以看出,prepareMainLooper方法中调用prepare()方法创建了一个Looper对象,并将这个Looper对象放进了ThreadLocal中,将
Looper对象放进ThreadLocal中的作用是,ThreadLocal会维护Looper对象中变量的副本。具体可以参考ThreadLocal的使用方法。然后调用myLooper
方法从ThreadLocal中获取Looper对象,并将其赋值给主线程Looper对象的引用。在Looper构造函数中我们可以看见,他创建了一个MessageQueue
对象,同时获取了Looper对象所在当前线程的引用。这样一个Looper对象便创建成功。
step2: 然后判断主线程的Handler是否为空,如果为空则默认创建一个Handler对象,但是在源码中这个默认的Handler时候从来就没使用过,
估计是既然已经默认创建了Looper,那么也默认创建一个Handler对象。
step3: 创建主线程ActivityThread对象,然后调用loop()方法
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
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;
}
long wallStart = 0;
long threadStart = 0;
// 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);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
msg.target.dispatchMessage(msg);
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// 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.recycle();
}
}
}
在loop方法中,首先获取之前创建的Looper对象,MessageQueue对象,清除所有之前的访问标志,然后下面就是一个while死循环,在这个while循环
中,通过Message msg = queue.next()不停的从消息队列中获取Message,然后判断获取的Message是否为空,不为空,则判断这个Message的target
是否为空,通过了解Message源码我们知道,这个target其实就是一个Handler对象,也就是如果在没有创建Handler对象,则这个Message不进行处理
直接返回,继续去下一个Message。如果已经创建了Handler对象,则通过msg.target.dispatchMessage(msg)将从消息队列中获取的Message传递
到Handler中。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在dispatchMessage中将消息传递到handlerMessage(msg)中,这样handler便接收到了一个Message。
通过上面三步,当一个Activity启动时,其主线程ActivityThread创建成功后,会默认创建一个Looper对象,一个消息队列。同时会循环遍历这个消息
队列,而不会管Handler对象有没有创建。
下面我们来看Handler是怎样发送一个消息进消息队列的,首先了解Hanlder的初始化过程:
public Handler() {
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 = null;
}
从Handler的构造函数中我们可以看到,通过Looper.myLooper()获取Looper对象的引用,通过mLooper.mQueue获取消息队列的引用。
接下来我们看发送消息的方法:
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) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
从上面源码可以看到,调用sendMessage其实是调用sendMessageDelayed方法,在sendMessageDelayed方法中调用了sendMessageAtTime方法
sendMessageAtTime才是最终发送Message的地方,在sendMessageAtTime中我们可以看到,首先判断消息队列的引用是否为空,不为空则调用
enqueueMessage方法将Message放进消息队列中。在这个方法中我们还可以看到通过msg.target = this,Message获取到了当前Handler对象的引用
final boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
final boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
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;
}
要理解enqueueMessage源码,就必须结合Looper获取消息的方法来理解:
final Message next() {
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(mPtr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
final Message msg = mMessages;
if (msg != null) {
final long when = msg.when;
if (now >= when) {
mBlocked = false;
mMessages = msg.next;
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
msg.markInUse();
return msg;
} else {
nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
}
} else {
nextPollTimeoutMillis = -1;
}
// If first time, then get the number of idlers to run.
if (pendingIdleHandlerCount < 0) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount == 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
在enqueueMessage中我们看到,首先判断Message的target即所属的Handler对象是否为空,为空则抛出RuntimeException异常,然后定义了一个
final boolean needWake变量,注意他没有进行初始化,而且为final类型,表明一旦其被初始化后就无法再次进行更改了,然后就是一个同步块,在
这个同步块中,首先获取一个全局Message对象mMessages的引用,如果这个Message不是延迟性或者空的消息,那么将这个msg赋值给这个全局
的Message对象mMessages,并且将mBlocked赋值给needWake,在MessageQueue源码中,可以看见mBlocked定义时是没有初始化的,那么
在哪里初始化呢?这就要看next()方法了。
我们知道在主UI线程创建时,Looper对象就会创建,就会调用loop()方法,就会调用next()方法循环遍历消息队列,由于一开始消息队列为空,所以
msg一定为空,执行的只是下面这段代码:
if (pendingIdleHandlerCount < 0) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount == 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
从这里就能够看见,mBlocked一开始是初始化为true的,所以在同步方法块执行完毕后,会调用nativeWake方法。在next()方法中可以看见,其消息
操作的逻辑也是一个同步方法块,而且注意到了没有?他操作的Message不是从什么队列中获取的,其实操作的就是那个全局的Message对象
mMessages,并且从MessageQueue的其他removeMessages等方法可以看到,所有操作全局对象mMessages都是在方法同步块中的,所以我们
就应该能够明白了MessageQueue不是用什么消息队列来保存Message的,而只是使用一个全局的mMessages来保存的,每次Looper循环遍历的
都是mMessages对象,获取到之后然后将这个对象置为空,如果next()在调用,则其他方法调用处于阻塞状态,如果enqueueMessage处于调用中
则其他调用的方法处于阻塞中,所以当有多个线程同时调用同一个Handler对象发送Message时,其中只有一个线程调用的方法是处于运行状态的,
其他线程的调用是处于阻塞状态的,为什么android会这样进行处理呢?我觉得这么处理的原因是以时间换取空间,Handler发送消息的逻辑是相对
简单的,没有什么业务逻辑,也就是所需获取执行的时间是非常短的,而且不会出现很多线程同时使用同一个Handler来发送Message。
所以到这里我们就明白了MessageQueue的实现机制了:
1、MessageQueue不是什么消息队列,没有使用到队列,其使用的是一个全局对象来进行消息接收与发送
2、MessageQueue中所有的消息操作方法都是同步块的,当有一个方法被执行时,其他方法是处于阻塞状态的。
3、如果我们同时开启非常多的线程使用同一Handler发送消息或者移除消息,那么sendMessage(msg)不会立即返回结果的。
4、在多个线程中不要大量使用Handler来操作Message。他只适合于少量线程中进行使用。
这样Handler的消息发送以及Looper的消息获取就都剖析完了。Handler,Looper,MessageQueue的实现也就完全讲完了。
总结:
在我们创建一个Activity时,会自动创建一个Looper对象,并且在Looper的构造方法中会创建一个MessageQueue的对象,当Activity的主线程启动
时,会调用Looper的loop()方法循环检查MessageQueue中的全局对象mMessages是否为空,如果不为空则会调用相应Handler的
dispatchMessage方法,将这个消息传递到Handler中的handleMessage方法中进行处理。当我们创建一个Handler对象,使用这个Handler对象
发送消息时,最终调用的是MessageQueue中的enqueueMessage,消息的所有的操作,如:发送,移除,遍历都是在MessageQueue中进行
操作的,这也对应了面向对象的及迪米特法则,也就是所有该类的职责应该就在该类中完成,尽量少于外界进行联系。消息的处理是单个操作的
当一个消息在发送时,其他消息的发送是处于阻塞状态,由于消息操作的业务逻辑简单,所以不必过于关注消息操作的延时性,但是不应在大量
线程中使用Handler进行消息传递。