浅析android线程处理和通信
做过java的朋友应该对java的线程类Thread很熟悉了,用法也很简单直观,简单写个最简单的例子:
public class A implements Runnable {
@Override
public void onCreate() {
//创建工作线程
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
//工作线程
}
}
在创建完thread,并把thread start以后,一个新的线程就开始调用run方法运行了。
原本这样就够用了,可是Android还是害怕我们用起来不方便,又提供了几个类让大家用起来更舒服,唉,没办法,谁让Android的架构中设计了那么多异步调用的方法呢。
这几个类包括:Handler、Looper和HandlerThread,要承认刚看到这三个玩艺很快调用的时候,我很快就有些晕了,SDK文档上的说明看了半天,明白了大体的工作方式,但就是总觉得不踏实,最后没办法,拉下这部分的源代码把这部分看了一下,才算是心里有了底。
先写一个这三个类常用的使用方法,看看能不能把你搞晕。
HandlerThread thread = new HandlerThread();
thread.start();
Looper looper = thread.getLooper();
Handler handler = new = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
//消息处理
}
};
....
//其他线程向thread线程发送消息
handler.sendEmptyMessage(0);
晕了也没事,看了我下面的话,应该能清醒个七七八八,如果再整不明白,就和我一样去看source吧。先从HandlerThread说起,这个类是继承自Thread,不过在调用的时候可就不一样了。Thread在构造的时候需要传递一个实现了Runnable接口的对象,当线程开始运行的时候,就会执行这个对象的run方法,可HandlerThread不需要你传递这个对象,因为它自己实现了这个run的方法,当线程创建运行的时候HandlerThread会执行自己的run.当然HandlerThread也不会白收钱不办事的,他会返回给你一个信物,就是Looper,用HandlerThread.getLooper的方法就可以。
先看一下HandlerThread的run中的代码,mLooper就是要返回给我们的信物了。而程序执行时会在Looper.loop()中不停的loop,直到执行Looper.quit方法。
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
Process.setThreadPriority(mPriority);
notifyAll();
}
onLooperPrepared();
Looper.loop();
mTid = -1;
}
Looper这东西基本上可以当他是一个被动的数据类型,主要的用途就是为一个线程做标示,确切的来说他包装了一个消息队列。每个线程都会唯一对应一个Looper对象,有了Looper以后我们还没有办法直接用,我们就可以用Handler来传递消息了,Handler构造的时候需要一个Looper做为参数,当然你不给他也可以,他会默认得到当前执行线程的Looper。这个handler构造好以后,就算是大功告成了,任何线程拿到这个handler都可以向这个线程发消息,这个消息是一个异步消息,执行完sendMessage方法以后会立即返回,而looper的属主线程就会来执行handler的handleMessage方法。如果上面说的还不够清楚,我们来看一下loop方法的实现:
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<<>
+ msg.callback);
msg.recycle();
}
}
}
在loop循环的时候会从队列中读取消息,当然即使队列中没有消息Looper也不会空循环,而是会block住,等有消息的时候会去调用消息target也就是handler的dispatchMessage方法,再由dispatchMessage将消息交给handleMessage执行。习惯hack代码的xd看到这里可能就会有想法,如果我在传递消息的时候把msg的target指定为其他的handler那样会不会就交给了其他的处理程序去处理,这部分Android已经给你处理掉了,在执行Handler的sendMessage的方法中都已经替你把msg的target填入了正确的值,所以这部分大可以放心使用。
这几个组件类似于Android提供的增值服务,如果你还是使用以往Java的Thread类的调用方式,在Android下也没什么问题。虽然这几个东西搞的比较复杂,但如果明白其中的实现原理,用起来还是挺方便的,起码一个完善的消息队列内部已经替你实现好了。Android内部也大都使用的这种实现方式,所以还是推荐大家尝试一下。
java代码在core目录下