Android处理程序:Handler Looper Message源码研究
线程Thread的线程变量ThreadLocal中,存放着这个线程的Looper;Looper在初始化时,会新建一个消息队列MessageQueue,之后Looper进入一个死循环,等待从消息队列MessageQueue取得消息Message(Looper是消费者),没有消息时会阻塞;
我们程序中的Handler,会通过sendMessage或post方法,往MessageQueue中添加消息时,添加的这个Message,会记录他是属于哪个Handler发出的,同时根据message.when,决定新添加的这个Message在Queue中的位置,MessageQueue中只有一个当前的Message,队列关系是通过Message中的prev,next维护的,Message是一个链表的节点;
添加消息后,消费者Looper取得Message,并调用建立Message的Hander的dispatchMessage方法。
咋一看好像Handler即sendMessage,又handlerMessage,事情还是只有一个线程在做事情。
但是后来想想,明白了这样设计的必要性。
因为这个唯一的线程一般而言,都是mainUI线程,如果你有个可以分成多个小任务的任务要处理,你没有使用Handler,直接执行,也许系统忙于处理你这个任务,而无法及时响应用户事件,从而导致ANR的抛出。
如果你把你的任务拆成几个小任务,用Handler来实现,那么系统就可以把你的小任务推到后面来处理,抽出时间来响应用户操作。
如果真的有大任务,一般式需要另外线程去处理,或者开启Service。
一个在新线程中使用handler例子,我们来分析下源码
Java代码
- newThread(newRunnable(){
- @Overridepublicvoidrun(){
- Handlerhandler;
- //1、初始化Looper
- Looper.prepare();
- //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法
- handler=newHandler(){
- @OverridepublicvoidhandleMessage(Messagemsg){
- }
- };
- //3、发送消息
- handler.sendMessage(newMessage());
- handler.post(newRunnable())
- handler.obtainMessage(1,"hello").sendToTarget();
- //4、启动消息循环
- Looper.loop();
- }
- }).start();
1Java代码
- publicstaticfinalvoidprepare(){
- if(sThreadLocal.get()!=null){//每个线程,只能有一个Looper对象
- thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");
- }
- //如果当前线程没有Looper,新建一个,构造函数是private的
- sThreadLocal.set(newLooper());
- }
- privateLooper(){
- mQueue=newMessageQueue();//建立消息队列
- mRun=true;
- mThread=Thread.currentThread();
- }
2Java代码
- publicHandler(){
- mLooper=Looper.myLooper();//取得当前线程的Looper,如果抛异常
- if(mLooper==null){
- thrownewRuntimeException(
- "Can'tcreatehandlerinsidethreadthathasnotcalledLooper.prepare()");
- }
- mQueue=mLooper.mQueue;//取得消息队列
- mCallback=null;
- }
3Java代码
- //不管调用哪个方法,最终执行的是
- publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis){
- booleansent=false;
- //取得消息队列
- MessageQueuequeue=mQueue;
- if(queue!=null){
- msg.target=this;//消息发出着是自己
- sent=queue.enqueueMessage(msg,uptimeMillis);//添加到消息队列中
- }
- else{
- RuntimeExceptione=newRuntimeException(
- this+"sendMessageAtTime()calledwithnomQueue");
- Log.w("Looper",e.getMessage(),e);
- }
- returnsent;
- }
- finalbooleanenqueueMessage(Messagemsg,longwhen){
- if(msg.when!=0){
- thrownewAndroidRuntimeException(msg
- +"Thismessageisalreadyinuse.");
- }
- if(msg.target==null&&!mQuitAllowed){
- thrownewRuntimeException("Mainthreadnotallowedtoquit");
- }
- synchronized(this){
- if(mQuiting){
- RuntimeExceptione=newRuntimeException(
- msg.target+"sendingmessagetoaHandleronadeadthread");
- Log.w("MessageQueue",e.getMessage(),e);
- returnfalse;
- }elseif(msg.target==null){
- mQuiting=true;
- }
- msg.when=when;
- Messagep=mMessages;
- //之前没有其他消息了,MessageQueue中当前消息mMessages就是传递进来的msg
- if(p==null||when==0||when<p.when){
- msg.next=p;
- mMessages=msg;
- this.notify();//唤醒
- }else{
- //之前有其他消息了,将传递的msg放到适合的位置,根据when
- Messageprev=null;
- while(p!=null&&p.when<=when){
- prev=p;
- p=p.next;
- }
- msg.next=prev.next;
- prev.next=msg;
- this.notify();//唤醒
- }
- }
- returntrue;
- }
4Java代码
- publicstaticfinalvoidloop(){
- Looperme=myLooper();
- MessageQueuequeue=me.mQueue;
- while(true){//死循环
- Messagemsg=queue.next();//当队列中没有消息时会阻塞
- if(msg!=null){
- if(msg.target==null){//消息没有发送者时,退出消息循环
- //Notargetisamagicidentifierforthequitmessage.
- return;
- }
- if(me.mLogging!=null)me.mLogging.println(
- ">>>>>Dispatchingto"+msg.target+""
- +msg.callback+":"+msg.what
- );
- //调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler
- msg.target.dispatchMessage(msg);
- if(me.mLogging!=null)me.mLogging.println(
- "<<<<<Finishedto"+msg.target+""
- +msg.callback);
- msg.recycle();
- }
- }
- }
- finalMessagenext(){
- booleantryIdle=true;
- while(true){
- synchronized(this){
- //没有消息的或,会阻塞
- try{
- if(mMessages!=null){
- if(mMessages.when-now>0){
- Binder.flushPendingCommands();
- this.wait(mMessages.when-now);
- }
- }else{
- Binder.flushPendingCommands();
- this.wait();
- }
- }
- catch(InterruptedExceptione){
- }
- }
- }
- }
总结
Handler作用:
1. 执行计划任务
2. 线程间通信
一个handler,只能接收到自己发出的message。handler实例与消息Message处理是关联的,发送和接受要匹配
Handler操作队列,主要是在子线程操作主线程的消息队列
Handler是实现异步的一种方式,用法是在主线程中建立Handler,(主线程中的Handler不用掉Looper.prepare);
在子线程(耗时操作)任务完成后sendMessage,这个Message会发送到主线程的消息队列中,主线程Handler的重写dispatchMessage方法,做新线程任务完成后的事情,大部分是更新UI。