您的位置:首页 > 移动开发 > Android开发

Android线程间通信——Looper Handler

2014-10-28 10:45 337 查看
首先先搞清楚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();
		}


下面创建一个该子线程的handler ,如下:

mAlbumArtWorker = new Worker("album art worker");//创建一个线程
mAlbumArtHandler = new AlbumArtHandler(mAlbumArtWorker.getLooper());//得到该线程的handler


Handler实现,主要在构造方法中是否包含子线程的looper对象

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;
			}
		}
	}


主线程获取到子线程的handler

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();

子线程间的通信实现原理跟上面是一样的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: