首先先搞清楚Looper handler messageQuee之间的关系
职责
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
关系
Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
这样说来,多个Handler都可以共享同一Looper和MessageQueue了。当然,这些Handler也就运行在同一个线程里。
· Handler的处理过程运行在创建Handler的线程里
· 一个Looper对应一个MessageQueue
· 一个线程对应一个Looper
· 一个Looper可以对应多个Handler
我们知道获取到主线程的handler 只要
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
就可以了。子线程只要持有主线程的mHandler就可以给主线程发消息。
那么,主线程如何给子线程发消息,或者说子线程之间怎么进行消息通信?
先看子线程
private static class Worker implements Runnable { private final Object mLock = new Object(); private Looper mLooper; /** * Creates a worker thread with the given name. The thread then runs a * {@link android.os.Looper}. * * @param name * A name for the new thread */ Worker(String name) { Thread t = new Thread(null, this, name); t.setPriority(Thread.MIN_PRIORITY); t.start(); synchronized (mLock) { while (mLooper == null) { try { mLock.wait(); } catch (InterruptedException ex) { } } } } public Looper getLooper() { return mLooper; } public void run() { synchronized (mLock) { Looper.prepare(); mLooper = Looper.myLooper();//得到该线程的looper mLock.notifyAll(); } Looper.loop();//让这个Looper跑起来(Looper.loop),抽取Message,这样,Handler才能正常工作 } public void quit() { mLooper.quit(); }
mAlbumArtWorker = new Worker("album art worker");//创建一个线程 mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());//得到该线程的handler
public AlbumArtHandler(Looper looper) { super(looper);//创建同拥有looper的子线程中的handler }因此, Handler 处理消息总是在创建 Handler 的线程里运行。而我们的消息处理中,不乏更新 UI 的操作,不正确的线程直接更新 UI 将引发异常。因此,需要时刻关心 Handler 在哪个线程里创建的。
public class AlbumArtHandler extends Handler { private long mAlbumId = -1; public AlbumArtHandler(Looper looper) { super(looper);//创建同拥有looper的子线程中的handler } @Override public void handleMessage(Message msg) {//处理消息是在创建handler的线程里执行 long albumid = ((AlbumSongIdWrapper) msg.obj).albumid; long songid = ((AlbumSongIdWrapper) msg.obj).songid; String albumName = ((AlbumSongIdWrapper) msg.obj).albumName; if (msg.what == GET_ALBUM_ART && (mAlbumId != albumid || albumid < 0)) { // while decoding the new image, show the default album art Message numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, null); mHandler.removeMessages(ALBUM_ART_DECODED); mHandler.sendMessageDelayed(numsg, 300); Bitmap bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, songid, albumid, albumName); if (bm == null) { bm = MusicUtils.getArtwork(MediaPlaybackActivity.this, songid, -1, albumName); albumid = -1; } if (bm != null) { mAlbumBm = null; mAlbumBm = bm; // while decoding the new image, show the default album art numsg = mHandler.obtainMessage(ALBUM_ART_DECODED, bm); mHandler.removeMessages(ALBUM_ART_DECODED);//mHandler是主线程的handler mHandler.sendMessage(numsg);<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">//给主线程发消息</span> } mAlbumId = albumid; } } }
mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());//得到该线程的handler就可以给子线程发消息了。
mAlbumArtHandler.removeMessages(GET_ALBUM_ART);
Message msg = mAlbumArtHandler.obtainMessage(GET_ALBUM_ART,
new AlbumSongIdWrapper(albumid, songid, albumName));
msg.arg1 = metaChanged ? 1 : 0;
msg.sendToTarget();
子线程间的通信实现原理跟上面是一样的