安卓msg handler looper详解

Message:frameworks\base\core\java\android\Os\Message.java

消息,其中包含了消息ID,消息处理对象(Handler)以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:frameworks\base\core\java\android\Os\Handler.java处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:frameworks\base\core\java\android\Os\MessageQueue.java

消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:frameworks\base\core\java\android\Os\Looper.java

消息循环,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

关系图如下:



消息处理流程:

 

class LooperThread extends Thread {
   public Handler mHandler;
   public void run() {
       Looper.prepare(); // 创建Looper并与本线程绑定  【第一步】
       mHandler = new Handler() {
           // 定义并实现Handler.handleMessage方法     【第二步】
           public void handleMessage(Message msg) {
                // process incoming messageshere
           }
       };      
       Looper.loop(); // 启动Looper消息循环           【第三步】
    }
}

相关源代码如下:

public static void prepare() {
       prepare(true);
}
    private static void prepare(booleanquitAllowed) {
        if (sThreadLocal.get() != null) {
            throw newRuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(newLooper(quitAllowed));  //新建一个looper对象,并保存到线程本地变量中
 
        /// M: ALPS00297986
        long instances =VMDebug.countInstancesOfClass(Looper.class, false);
       
        // check if the looper instance over alimit, it should has some leakage.
        if(100 < instances)
        {
            Log.e(TAG,"WARNING: The Looperclass instance count has over a limit(100). There should be some leakage ofLooper or HandlerThread.");
            Log.e(TAG,"Looper classinstance count = " + instances);
            Log.e(TAG,"Current ThreadName: " + Thread.currentThread().getName());
           Thread.currentThread().getThreadGroup().list();
            Thread.currentThread().dumpStack();
        }//if
        /// M: ALPS00297986
    }
 
   private Looper(boolean quitAllowed) {
       mQueue = new MessageQueue(quitAllowed); //新建一个消息队列
       mThread = Thread.currentThread();        //保存当前线程
}

新建handler并初始化:

publicHandler() {
        this(null, false);
    }
 
    public Handler(Callback callback, booleanasync) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extendsHandler> klass = getClass();
            if ((klass.isAnonymousClass() ||klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() &Modifier.STATIC) == 0) {
                Log.w(TAG, "The followingHandler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
 
        mLooper = Looper.myLooper();   //获取当前线程的looper
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handlerinside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
 

消息循环:

public staticvoid loop(){
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("NoLooper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
 
        // Make sure the identity of thisthread is that of the local process,
        // and keep track of what that identitytoken actually is.
        Binder.clearCallingIdentity();
        final long ident =Binder.clearCallingIdentity();
 
        for (;;) {    //dead loop
            Message msg = queue.next(); //might block
            if (msg == null) {
                // No message indicates thatthe message queue is quitting.
                return;
            }
 
            // This must be in a localvariable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
               logging.println(">>>>> Dispatching to " +msg.target + " " +
                        msg.callback + ":" + msg.what);
            }
 
            /// M: MSG Logger Manager @{
            if(!IS_USER_BUILD) {
                Printer msglogging =me.mMsgMonitorLogging;
                if (msglogging != null) {
                   msglogging.println(">>>>> Dispatching to " +msg.target + " " +
                            msg.callback +": " + msg.what);
                }
 
                if(MessageMonitorLogger.monitorMsg.containsKey(msg) ) {
                   MessageMonitorLogger.MonitorMSGInfo monitorMsg =MessageMonitorLogger.monitorMsg.get(msg);
                   if(MessageMonitorLogger.mMsgLoggerHandler.hasMessages(MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,monitorMsg )) {
                       Log.d("Looper", "RemoveMessages PENDING_TIMEOUT_MSG msg="+msg);
                       MessageMonitorLogger.mMsgLoggerHandler.removeMessages(MessageMonitorLogger.START_MONITOR_PENDING_TIMEOUT_MSG,monitorMsg);
                        try {
                            if(monitorMsg.executionTimeout>100) {
                                Message msg1 =MessageMonitorLogger.mMsgLoggerHandler.obtainMessage(MessageMonitorLogger.START_MONITOR_EXECUTION_TIMEOUT_MSG,monitorMsg);
                               MessageMonitorLogger.mMsgLoggerHandler.sendMessageDelayed(msg1, monitorMsg.executionTimeout);
                            } else {
                               MessageMonitorLogger.monitorMsg.remove(msg);
                               if(monitorMsg.executionTimeout !=MessageMonitorLogger.DISABLE_MONITOR_EXECUTION_TIMEOUT_MSG)
                                    throw newIllegalArgumentException("Execution timeout <100 ms!");
                            }
                        } catch(Exception e) {
                            Log.d(TAG,"Execution timeout exception "+e);
                        }
                    }
                }
            }
            /// M: MSG Logger Manager @}
 
            msg.target.dispatchMessage(msg);//对消息进行分发处理
 
            if (logging != null) {
                logging.println("<<<<<Finished to " + msg.target + " " + msg.callback);
            }
 
            /// M: MSG Logger Manager @{
            if(!IS_USER_BUILD) {
                Printer msglogging =me.mMsgMonitorLogging;
                if (msglogging != null) {
                   msglogging.println("<<<<< Finished to " +msg.target + " " + msg.callback);
                }
                if(MessageMonitorLogger.monitorMsg.containsKey(msg) ) {
                   MessageMonitorLogger.MonitorMSGInfo monitorMsg = MessageMonitorLogger.monitorMsg.get(msg);
                   if(MessageMonitorLogger.mMsgLoggerHandler.hasMessages(MessageMonitorLogger.START_MONITOR_EXECUTION_TIMEOUT_MSG,monitorMsg )) {
                       Log.d("Looper", "RemoveMessages EXECUTION_TIMEOUTmsg="+msg);
                       MessageMonitorLogger.mMsgLoggerHandler.removeMessages(MessageMonitorLogger.START_MONITOR_EXECUTION_TIMEOUT_MSG,monitorMsg);
                       MessageMonitorLogger.monitorMsg.remove(msg);
                    }
                }
            }
            /// MSG Logger Manager @}
            // Make sure that during the courseof dispatching the
            // identity of the thread wasn'tcorrupted.
            final long newIdent =Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Threadidentity changed from 0x"
                        +Long.toHexString(ident) + " to 0x"
                        +Long.toHexString(newIdent) + " while dispatching to "
                        +msg.target.getClass().getName() + " "
                        + msg.callback + "what=" + msg.what);
            }
 
            msg.recycle();
        }
    }

将消息发送到消息队列:

        private Message createMessage(Handlerhandler,String str) { 
            Message msg =handler.obtainMessage(); 
            Bundle data = new Bundle(); 
            data.putString("message", str); 
            msg.setData(data); 
            return msg; 
       }  
 

为什么继承activity 之后不需要:

Looper.prepare() 和Looper.loop();

直接实现一个handler之后,就可以实现消息处理流程?

下图为activity的启动流程:




Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。详细实现请参考ActivityThread.java文件

Android应用程序进程在启动的时候,会在进程中加载ActivityThread类,并且执行这个类的main函数,应用程序的消息循环过程就是在这个main函数里面实现的

public final classActivityThread {
    ......
    public static final void main(String[] args) {
       ......
       Looper.prepareMainLooper();
       ......
       <span style="color:#ff0000;">ActivityThread thread = new ActivityThread();</span>
       thread.attach(false);
       ......
      <span style="color:#ff0000;"> Looper.loop();</span>
     ......
	thread.detach();
	......
    }
}

这个函数做了两件事情,一是在主线程中创建了一个ActivityThread实例,二是通过Looper类使主线程进入消息循环中


测试源码请参考:

http://download.csdn.net/detail/u010657219/8145063


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值