简介
我们在上篇文章《Android的消息机制(一)》中提到,线程默认是没有Looper的,只能向存在Looper的线程发消息,否则会抛RuntimeException异常。所以我们也知道主线程在被创建时就创建了Looper。今天我们继续来讲讲消息机制中Looper在主线程中是怎样被创建 和 我们自己创建的子线程中能否也创建Looper来接收消息。
主线程的消息循环
Android的主线程就是ActivityThread,ActivityThread中的入口方法Main(),该方法下你会发现有:Looper.prepareMainLooper() 和 Looper.loop()两行代码。其中,prepareMainLooper方法是prepare的封装。上一篇文章中提到过,通过Looper.prepare()即可为当前线程创建一个Looper,接着通过Looper.loop()来开启消息循环。所以ActivityThread中的Main方法源码如下所示:
public static void main(String[] args) {
SamplingProfilerIntegration.start();
…
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler== null) {
sMainThreadHandler= thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
子线程中Looper的创建和使用
虽然我们知道了要使用handler就必须在接收线程中存在Looper,而创建Looper的过程也在ActivityThread源码中查阅到。所以接下来,我们通过Demo来验证子线程接收消息是如何做的,代码如下:
public class MainActivity extends AppCompatActivity {
private final static int MSG_SCAN_START = 0;
private final static int MSG_SCAN_END = 1;
private LooperThread mLooperThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLooperThread= new LooperThread("looperThread");
mLooperThread.start();
new Thread("Thread1") {
@Override
public void run() {
try {
Thread.sleep(1000); // 为了要让LooperThread都初始化完成,这里等待1秒钟
mLooperThread.mHandler.sendEmptyMessage(MSG_SCAN_START);
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
} finally {
Message msg = mLooperThread.mHandler.obtainMessage();
msg.what= MSG_SCAN_END;
msg.obj = true;
mLooperThread.mHandler.sendMessage(msg);
}
// 这是通过post发消息
mLooperThread.mHandler.post(new Runnable() {
@Override
public void run() {
Log.e("zyx", "线程名:" + Thread.currentThread().getName() + ",这是通过post发的消息");
}
});
}
}.start();
}
class LooperThread extends Thread {
public Handler mHandler;
public LooperThread(String threadName) {
super(threadName);
}
public void run() {
Looper.prepare();
mHandler= new Handler() {
public void handleMessage(Message msg) {
int what = msg.what;
Object obj = msg.obj;
switch (what) {
case MSG_SCAN_START:
Log.e("zyx", "线程名:" + Thread.currentThread().getName() + ",OnScanStart");
break;
case MSG_SCAN_END:
booleanresult = (boolean)obj;
Log.e("zyx", "线程名:" + Thread.currentThread().getName() + ",OnScanEnd:" + result);
break;
}
}
};
Looper.loop();
}
}
}
代码相对比较简单,在Thread1线程中,为了让LooperThread能初始化完成,所以特意做了1秒钟的等待,然后分别用:sendEmptyMessage、sendMessage 和 post三种方式发出了3个消息,我们一起来看看输出结果:
D/zyx: 线程名:looperThread,OnScanStart
D/zyx: 线程名:looperThread,OnScanEnd:true
D/zyx: 线程名:looperThread,这是通过post发的消息