专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
鸿洋  ·  Android×AI×鸿蒙生态周刊#2|跨端 ... ·  昨天  
开发者全社区  ·  WC!阿里P7总包超150w ·  昨天  
开发者全社区  ·  年薪300万大厂程序员被女友晒工资单被裁,百 ... ·  昨天  
开发者全社区  ·  字节跳动出手:直接辞退353人! ·  2 天前  
开发者全社区  ·  私募大瓜PDF ·  3 天前  
51好读  ›  专栏  ›  安卓开发精选

Android Handler 消息机制(解惑篇)下

安卓开发精选  · 公众号  · android  · 2016-10-12 09:59

正文

(点击 上方公众号 ,可快速关注)


来源:伯乐在线专栏作者 - PleaseCallMeCoder

链接:http://android.jobbole.com/84957/

点击 → 了解如何加入专栏作者


接上文


接下来我们看一下handler是如何发送消息的


/**

* Causes the Runnable r to be added to the message queue.

* The runnable will be run on the thread to which this handler is

* attached.

*

* @param r The Runnable that will be executed.

*

* @return Returns true if the Runnable was successfully placed in to the

*         message queue.  Returns false on failure, usually because the

*         looper processing the message queue is exiting.

*/

public final boolean post ( Runnable r )

{

return sendMessageDelayed ( getPostMessage ( r ), 0 );

}

/**

* Enqueue a message into the message queue after all pending messages

* before (current time + delayMillis). You will receive it in

* {@link #handleMessage}, in the thread attached to this handler.

*

* @return Returns true if the message was successfully placed in to the

*         message queue.  Returns false on failure, usually because the

*         looper processing the message queue is exiting.  Note that a

*         result of true does not mean the message will be processed -- if

*         the looper is quit before the delivery time of the message

*         occurs then the message will be dropped.

*/

public final boolean sendMessageDelayed ( Message msg , long delayMillis )

{

if ( delayMillis 0 ) {

delayMillis = 0 ;

}

return sendMessageAtTime ( msg , SystemClock . uptimeMillis () + delayMillis );

}

/**

* Enqueue a message into the message queue after all pending messages

* before the absolute time (in milliseconds) uptimeMillis .

* The time-base is {@link android.os.SystemClock#uptimeMillis}.

* Time spent in deep sleep will add an additional delay to execution.

* You will receive it in {@link #handleMessage}, in the thread attached

* to this handler.

*

* @param uptimeMillis The absolute time at which the message should be

*         delivered, using the

*         {@link android.os.SystemClock#uptimeMillis} time-base.

*

* @return Returns true if the message was successfully placed in to the

*         message queue.  Returns false on failure, usually because the

*         looper processing the message queue is exiting.  Note that a

*         result of true does not mean the message will be processed -- if

*         the looper is quit before the delivery time of the message

*         occurs then the message will be dropped.

*/

public boolean sendMessageAtTime ( Message msg , long uptimeMillis ) {

MessageQueue queue = mQueue ;

if ( queue == null ) {

RuntimeException e = new RuntimeException (

this + " sendMessageAtTime() called with no mQueue" );

Log . w ( "Looper" , e . getMessage (), e );

return false ;

}

return enqueueMessage ( queue , msg , uptimeMillis );

}

private boolean enqueueMessage ( MessageQueue queue , Message msg , long uptimeMillis ) {

msg . target = this ;

if ( mAsynchronous ) {

msg . setAsynchronous ( true );

}

return queue . enqueueMessage ( msg , uptimeMillis );

}


这里我们只列出了一种调用关系,其他调用关系大同小异,我们来分析一下


  1. 调用getPostMessage(r),把runnable对象添加到一个Message对象中。

  2. sendMessageDelayed(getPostMessage(r), 0),基本没做什么操作,又继续调用sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)方法,在这个方法里拿到创建这个Handler对象的线程持有的MessageQueue。

  3. 调用enqueueMessage(queue, msg, uptimeMillis)方法,给msg对象的target变量赋值为当前的Handler对象,然后放入到MessageQueue。


那发送消息说完了,那我们的消息是怎样被处理的呢?


我们看到message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码。


/**

* Callback interface you can use when instantiating a Handler to avoid

* having to implement your own subclass of Handler.

*

* @param msg A {@link android.os.Message Message} object

* @return True if no further handling is desired

*/

public interface Callback {

public boolean handleMessage ( Message msg );

}

/**

* Subclasses must implement this to receive messages.

*/

public void handleMessage ( Message msg ) {

}

/**

* Handle system messages here.

*/

public void dispatchMessage ( Message msg ) {

if ( msg . callback != null ) {

handleCallback ( msg );

} else {

if ( mCallback != null ) {

if ( mCallback . handleMessage ( msg )) {

return ;

}

}

handleMessage ( msg );

}

}

private static void handleCallback ( Message message ) {

message . callback . run ();

}


我们看到这里最终又调用到了我们重写的handleMessage(Message msg)方法来做处理子线程发来的消息或者调用handleCallback(Message message)去执行我们子线程中定义并传过来的操作。


思考


为什么要有Handler机制


这个问题可以这么考虑


  • 我们如何在子线程更新UI?——使用Handler机制传递消息到主线程(UI线程)

  • 为什么我们不在子线程更新UI呢?——因为Android是单线程模型

  • 为什么要做成单线程模型呢?——多线程并发访问UI可能会导致UI控件处于不可预期的状态。如果加锁,虽然能解决,但是缺点也很明显:1.锁机制让UI访问逻辑变得复杂;2.加锁导致效率低下。


Handler机制与命令模式


我在之前分享过Android源码中的命令模式,我们仔细分下一下不难看出Handler机制其实是一个非典型的命令模式。


  • 接收者:Handler,执行消息处理操作。

  • 调用者:Looper,调用消息的的处理方法。

  • 命令角色:Message,消息类。

  • 客户端:Thread,创建消息并绑定Handler(接受者)。


Android主线程是如何管理子线程消息的


我们知道Android上一个应用的入口,应该是ActivityThread。和普通的Java类一样,入口是一个main方法。


public static void main (







请到「今天看啥」查看全文