Android在Java标准线程模型的基础上,提供了消息驱动机制,用于多线程之间的通信。基于消息驱动机制的线程通信模型称为称为线程消息通信。在标准线程模型中,可以首先在线程内部创建一个消息队列,然后让线程进入一个无限循环中,在这个无限循环中,线程会不断检查消息队列中是否有消息。如果需要线程执行某个任务,便向线程的消息队列中发送对应的该任务的消息,线程在无限循环中检查到消息队列中有消息到来,便会获取该消息,进而执行该消息对应的处理流程。如果线程的消息队列中没有消息,线程便进入等待状态,等待消息的到来。这样便可以通过消息控制线程的执行,因此也称为消息驱动机制。

           消息驱动机制涉及的4个概念:消息、消息队列、消息循环、消息处理器。

             消息用于表示一个可执行任务,通常在消息内部会封装消息的标志、消息的执行时间以及消息数据。消息创建完毕后,通过消息处理器将其发送到象策划过的消息队列中,消息队列维护当前可执行消息的列表。当前线程进入消息循环中遍历消息队列获取消息,然后根据消息标志通知消息处理器执行对应的处理函数。

Looper线程:

               Android基于Java标准线程模型开发了Looper 线程,用于实现消息驱动机制。Looper 线程与标准线程的区别在于:Looper 线程的run 方法执行后并不会立即退出,而是进入一个loop 消息循环中等待消息的到来,然后根据消息类型分别作出不同的处理。这样,后台中只需要运行单一线程,当需要定时或者不定时执行不同任务时,分别发送不同的消息给Looper 线程去处理,这样就避免了频繁创建/销毁线程所带来的开销。

               Looper线程首先是一个Thread,由Java 标准线程演化而来。将一个普通线程变成Looper 线程只需要以下代码:

class LooperThread extends Thread{//继承自Thread
	public Handler mHandler;//需要一个handler 对象发送和处理消息
	public void run(){
		Looper.prepare();//Looper 线程准备阶段
		mHandler = new Handler(){//初始化消息处理器
			public void handlerMessage(Message message){
				//处理消息的逻辑
			}
		};
		Looper.loop();//Looper线程循环阶段
	}
}

通过上面的代码我们得出在Looper线程启动后进入run 方法后执行了一下三步操作:

  1. 调用Looper.prepare  方法进入Looper 线程准备阶段。
  2. 创建Handler 对象用于实现消息处理器,消息处理器负责发送和处理消息。
  3. 调用Looper.loop 方法进入Looper 线程循环阶段。

通过以上三步,Looper 线程提供了消息驱动机制的消息队列、消息循环和消息处理器。

第一阶段:Looper 线程准备阶段:

public class Looper {
	//定义一个线程局部对象存储Looper对象
	static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
	private static Looper sMainLooper;
	final MessageQueue mQueue;
	final Thread mThread;
	volatile boolean mRun;
	private Printer mLogging;
	
	//将当前线程初始化为一个Looper 线程,进入线程准备阶段
	public static void prepare(){
		prepare(true);
	}
	
	private static void prepare(boolean quitAllowed){//重载方法
		//每个线程只允许有一个Looper 实例
		if (sThreadLocal.get() != null) {
			throw  new RuntimeException("Only one Looper may be created pre thread");
		}
		/*
		 * 创建Looper 对象并存入SThreadLocal,这样每个调用prepare 
		 * 方法的线程将创建本线程唯一的Looper 对象
		 */
		sThreadLocal.set(new Looper(quitAllowed));
	}
	
	public static Looper myLooper(){//用于返回当前线程的Looper 对象
		return sThreadLocal.get();
	}
}

从以上源代码可以看出:在对应的线程中只能调用一次prepare 方法,如果多次调用prepare 方法会导致线程异常退出,综上所述prepare 方法创建了一个线程独立且唯一的Looper 对象,如果要访问这个Looper 对象,只需要调用myLooper 方法

第二阶段:消息处理器Handler

Handler 是Looper 线程的消息处理器,创建并初始化Handler 是Looper 线程运行过程中的关键步骤之一。Looper 线程是由消息驱动 的,Message便是消息的载体,Handler 承担了消息驱动机制的发送消息和处理消息两部分工作,创建Handler 对象的过程并没有特别之处,就是将之前在本线程中创建的Looper 和 MessageQueue 关联到其成员变量之中,这样Looper 、MessageQueue和Handler就连在一起了。Handler 的成员变量mMessenger 用于跨进程发送消息。

Message 实现了Parcelable 接口,这相当于Java的序列化和反序列化机制。可序列化保证Message 对象可以通过Intent 或者 Binder 远程传递。

  1. what 成员变量表示消息的消息码,用于唯一标识一条消息。
  2. when 成员变量表示消息在什么时间执行,取值为0表示立即执行。Message在消息队列中是按照消息执行时间  when 排列的。
  3. next  成员变量用于表示下一条消息,因此Message 本身实现了一个单向链表结构。
  4. sPool  用于表示消息池,每次调用obtain 方法相当于取出消息池头部的消息。

第三阶段:Looper 线程循环阶段

Looper 线程完成准备和初始化Handler 的工作后,便进入Loop 方法。

public static void loop(){
		final Looper me = myLooper();//获取线程局部变量中存储的Looper 对象
		if (me == null) {//调用loop 方法必须首先调用prepare 方法。
			throw new RuntimeException("No looper:Looper.prepare() was't called on this thread"); 
		}
		final MessageQueue queue = me.mQueue;//获取Looper 中存储的 MessageQueue
		Binder.clearCallingIdentity();//在IPCThreadState 中记录当前线程所属的PID和UID
		final long ident = Binder.clearCallingIdentity();
		for(;;){//在无限循环中轮询MessageQueue
			Message msg = queue.next();//可能阻塞
			if(msg == null){
				//无消息时,消息队列退出
				return;
			}
			Printer logging = me.mLogging;
			msg.target.dispatchMessage(msg);//将读取的消息发送到消息处理器
			final long newIdent = Binder.clearCallingIdentity();
			if (ident != newIdent) {
			}
			<strong>msg.recycle();//将处理过的消息重新初始化并放入消息池中
		}
	}

Loop方法的主要工作可以分为

四部分:

  1. 调用Binder.clearCallingIdentity方法记录并获取当前线程身份信息
  2. 调用MessageQueue.next  方法循环监听获取消息
  3. 调用Message 中的target 成员变量的dispatchMessage ,分发消息到处理器.
  4. 调用Message 的recycle()  方法,回收消息并更新消息。回收消息的过程只是将消息的成员变量清空(置为0),并没有回收消息对象本身,因此消息被回收后,不能直接操作该消息。