android下的线程,Looper线程,MessageQueue,Handler,Message等之间的关系,以及Message的send/post及Message dispatch的过程。 Looper线程我 们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和 MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和 MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我 们可以先看一下android source code的注释中给出的一种Looper线程的实现方式:
可以看到,就是在线程的run()方法中,调用Looper.prepare() 做一些初始化,然后创建一个Handler对象,最后执行Looper.loop()即开始了整个的事件循环。就是这么的简单,一个可以使用消息队列来管 理线程执行流程的Looper 线程就创建好了。 接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:
可 以看到,它做的事情就是为当前的线程创建了一个Looper对象,并存储在一个静态的线程局部变量中。在Looper的构造函数中创建了 MessageQueue,同时Looper会引用到当前的线程,并将一个表示状态的变量mRun设置为true。对于此处的线程局部变量 sThreadLocal,可以理解为就是一个HashMap,该HashMap中存放的数据其类型为Looper,而HashMap的key则 Thread.currentThread()。 启动Looper线程就和启动普通的线程一样,比如:
同样是new一个Thread对象,然后执行该对象的start()方法。 其实Looper线程有两种,一种就是我们上面看到的那种普通的Looper线 程,另外一种则是main loop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用 Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:
比较特别的地方即在于,此处调用prepare()方法传进去的参数为false,即表示这个Looper不能够被quit掉。其他倒是基本一样。整个android系统中,调用到prepareMainLooper()方法的大概有两处: 一处在ServerThread的run()方法中,用于为system server主线程初始化消息队列等,另外一处在ActivityThread的run()方法中,自然即是创建android app主线程的消息队列了。 通过消息与Looper线程交互那 Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。 那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得 到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢? 回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:
然后是向Looper线程发送消息的部分的写法:
向一个Looper线程发送消息的过程,基本上即是,调用Message.obtain()或Handler.obtainMessage()获取一个Message对象->设置Message->调用 Looper线程中创建的Handler对象来发送消息。 Handler 究竟是如何知道要向哪个MessageQueue中发送消息呢,从前面的code中,我们找不到任何将Handler与特定的MessageQueue关 联起来的代码,这究竟是怎么回事呢?这也是我们强调要使用Looper线程中创建的Handler对象来向该Looper线程中发送消息的原因。我们可以 看一下Handler对象构造的过程:
可以看到,很简单,是通过Looper.myLooper()获取到当前线程的 Looper对象,并与相关的MessageQueue等关联起来的。这也是前面我们在实现Looper线程时,要在其run方法中创建一个public 的Handler的依据。当然,我们也可以在构造Handler对象时,显式地使其与特定的Looper对象关联起来。 Handler提供了两组函数用于向一个Looper线程的MessageQueue中发送消息,分别是postXXX()族和sendXXX()族。可以先看一下sendXXX()族的实现:
绕来绕去,最终都是调用MessageQueue的 enqueueMessage()方法来将一个Message放入一个MessageQueue中。值得注意的是,在 Handler.enqueueMessage()中,会将Message的target设置为this,这实际上是决定了Looper的消息循环中,在 dispatch/handle message时将会使用的Handler。即,在default情况下,处理message的那个handler也将会是发送此message的 handler。 Handler实际的职责,并不像它的名称所显示的那样,其实它不仅仅是处理message,它还负责发送Message给线程的MessageQueue。 再来看一下MessageQueue的enqueueMessage()方法的code:
整个将Message放入MessageQueue的算法也还算比较清晰简洁,并 没有什么太绕的地方。此处我们可以一览MessageQueue中保存Messages的结构,即,MessageQueue用一个单向链表来保存所有的 Message,而链表中各个Message则按照其请求的执行时间先后来排列。 向Looper 线程的MessageQueue中发送消息的另外一族方法postXXX(),其实现同前面的sendXXX()族方法也大同小异啦:
Post的message,其callback将是传入的Runnable对象,其他就与send的message一样了。 消息队列中消息的处理消息队列中的消息是在Looper.loop()中被处理的:
这个函数会调用Handler的dispatchMessage()方法来处理消息,其实也就是msg.target对象的dispatchMessage()方法。 此外我们可以看到,在Looper.loop()方法的末尾recycle了从MessageQueue中取出的已经dispatch的消息。从而,我们 需要通过Handler向一个Looper线程的MessageQueue中发送消息时,我们只要obtain一个Message然后发送就好了,而不需 要自己手动去recycle,这些事情将会由Looper来帮助我们完成。接着来看Handler. dispatchMessage()的实现: 在Message的callback成员为非空时,会执行 handleCallback(msg),否则的话会依据Handler的mCallback是否为空来确定是否要执行 mCallback.handleMessage(msg),并执行Handler的handleMessage(msg)。Handler的handleMessage()方法通常需要override,来实现消息处理的主要逻辑。而mCallback则使得开发者可以比较容易的添加一种对Message做一些额外检测的机制,以提升消息处理的效率。 接着我们看一下,Handler.handleCallback(msg)的实现: |
|