首先简单说一下进程与线程的区别。进程(Process) 是程序的一个运行实例,以区别于“程序”这一静态的概念而线程(Thread)则是cpu调度的基本单位。也可以这样想,进程是划分程序所得到的内存区域,而线程是对cup调度的划分。
在我们第一印象中Handler,MessageQueue,Looper之间的关系在头脑或许是不相关的,怎么也联系不起来。但在使用中它们又感觉是一体的,这是怎么回事呢?
我们简单的说下他们是干嘛的:Handler相当于事情的处理者,怎么去处理消息由它决定。MessageQueue是一个线程所有消息存放的地方。而Looper它的任务就是推动这些消息执行,它是一个死循环,不断从MessgeQueue中取出消息交给对应的Handler处理。Handler是消息的发起者也是执行者,至于为什么大费周章的让它走这样的流程,是为了保证其“有序性”。
一个线程只有一个Looper,Looper只对应一个MessageQueue,而MessageQueue中可以有很对Message,但每个Message只对应一个Handler去处理。
关于Handler,我们平时可能是下面这样用的。
在主线程中:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
switch(msg.what){
//我们处理的事情
}
}
};
在子线程中:
Message message = Message.obtain();
message.what = HELLO_WORD;
handler.sendMessage(message);
或者
mHandler.post(new Runnable() {
@Override
public void run() {
//更新UI
}
});
这样我们在子线程中发的指令 ,就可以在主线程执行了 。在子线程里调用post(),传了一个Runable进去,并在run();方法中执行更新UI操作 。这种看似在子线程里更新UI又是怎么回事呢?我们带着这些疑问探究下源码吧。
我们看看使用Looper线程的普通线程和主线程的列子:
普通线程:
class myThread extends Thread{
public Handler mHandler ;
public void run(){
//第一步
Looper.prepare();
//第二步
mHandler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
//我们处理的事情
}
}
};
//第三步
Looper.loop;
}
}
主线程:
frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
... ...
//第一步,和普通线程有点点区别,稍后我们再分析
Looper.prepareMainLooper();
//创建一个线程对象
ActivityThread thread = new ActivityThread();
thread.attach(false);
//第二步 ,不是new的Handler而是thread.getHandler();
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
... ...
//第三步一样
Looper.loop();
可以看到两者的整体架构是一样的;
我们先看第一步:Looper.prepareMainLooper()。
frameworks\base\core\java\android\os\Looper.java
public static void prepareMainLooper() {
prepare(false);//和普通线程一样先是调用了prepare;传入false代表线程不允许退出
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//将其赋值给sMainLooper ,以表示主线程和其他线程不同;让其他进程都可以获取到主线程的looper对象(getMainLooper());
sMainLooper = myLooper();
}
}
接下来我们看看 prepare()做了什么?
//这个可以理解为放Looper对象那个的容器
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//新建一个Looper对象,将其放入Looper容器中
sThreadLocal.set(new Looper(quitAllowed));
}
顺便看看Looper的构造函数
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
到现在为止我们还是没看到Looper和Handler之间的联系;
我们继续看第二步mHandler = new Handler();
看看Hand的构造函数:
frameworks\base\core\java\android\os\Handler.java
ublic Handler(Callback callback, boolean async) {
... ...
//拿出第一步创建的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//拿出Looper对象中的MessageQueue;
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这样就巧妙的将它们之间联系起来了。
我们来走一下消息处理过程,以便于更好理解:
handler.sendMessage(message);
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;
}
//将消息放到MessageQueue;
return enqueueMessage(queue, msg, uptimeMillis);
}
我们来看看post()有什么不同
public final boolean post(Runnable r)
{
//就比sendMessage多一步 ,通过getPostMessage(r)将Runnable 封装为Message再将其放入MessageQueue中
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
现在我们已经将消息放进去了 ,那怎么执行起来呢?
就是第三步Looper.loop();
frameworks\base\core\java\android\os\Looper.java
public static void loop() {
//获取当前线程的Looper对象的实例
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//取出其中的MessageQueue ;
final MessageQueue queue = me.mQueue;
... ...
for (;;) {
//开始循环处理
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
... ...
try {
//交给了Message的target的dispatchMessage处理。
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
... ...
msg.recycleUnchecked();
}
}
由上我们可以得知,Looper循环处理MessageQueue中的message。最终将message给了message的target的dispatchMessage处理。
进一步探究target是何方神圣:
在Message中是个成员变量。
在前面发送消息的流程中我们走到了 enqueueMessage(queue, msg, uptimeMillis);
我们继续看看:
frameworks\base\core\java\android\os\Handler.java
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//在这里把Handler对象自己赋值给了target ,是不是感觉绕了个圈又回来了
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//将消息压如队列中的具体实现,有兴趣的可以自行阅读源码
return queue.enqueueMessage(msg, uptimeMillis);
}
好了现在我们知道了,通过message自己对应的Handler对象去处理。
最后我们看看Handler的dispatchMessage(msg);
public void dispatchMessage(Message msg) {
//在msg.callback不为空的情况下优先通过msg.callback处理,也就是使用Post()时传入的Runnabler对象
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
//在创建handler对象时如果传入了回调方法 ,则优先该回调方法
if (mCallback.handleMessage(msg)) {
return;
}
}
//最后有创建handler复写的handleMessage()进行处理
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
//看这里明白了吧 ,看似开启了一个子线程。其实是在拥有该handler对象的线程进行出理的
message.callback.run();
}