Android 消息系统解析(Handler.class及相关类源码解析)

来源:互联网 发布:物资采购软件 百度云 编辑:程序博客网 时间:2024/05/17 04:39

额,新手,第一次发文章...前几天写文档的时候发现网上的教程。。都不是很详细,反正不是很适合我这种新手....所以在整理之后就发上来了。顺便,不会弄目录,大家将就着看下吧。。

 

1.Handler概念 2

1.1为什么要用Handler 2

1.2 Handler运行流程 2

1.3 Handler的作用 2

1.4 Handler的作用 3

2.Handler.class源码解析 5

2.1 Handler的构造方法 5

2.2 Handler对消息的发送 6

2.3  Handler对消息的处理 8

3、 代码具体分析 8

3.1  Message.class 8

3.1.1Message.class各属性解析 8

3.2 MessagePool消息池原理及代码分析 9

3.2.1 Message的构造方法 9

3.2.2为什么要创建消息池 10

3.2.3 MessagePool的建立 11

3.2Looper源码解析 11

3.2.1 Looper.prepare();方法解析 12

3.3ThrealLocal<T> 13

ThreadLocal<T>概述 14

ThreadLocal<T>的接口方法 14

实现原理/流程图 15

Thread与同步机制比较 15

Threadlocal小结 16

为什么要在Looper中使用ThreadLocal 16

3.4 Looper.loop();-----------启动消息循环 16

3.5MessageQueue.class源码分析 17

3.5.1 MessageQueue类的介绍: 17

3.5.2 IdleHandler接口解析; 18

3.5.3 next()方法解析; 19

3.6 equeueMessage方法解析

 

以下内容只是对Handler、Message、MessageQueue、Looper、的源代码以及相关知识的一个简单的解析,至于深入的分析还没有涉及,如果有错误请大家多多指正,共同学习,谢谢!

1. Handler概念

1.1为什么要用Handler

在Android里,子线程不能更改主线程的UI

一般来说,所有显示在界面上的控件,都是由主线程创建的

每个主线程都有一个Handler,Handler运行在主线程里,它与子线程可以通过Message对象来传递数据

1.2 Handler运行流程

 主线程里都维护了一个消息对列(message queue),子线程通过Message实例设置消息内容,通过主线程里的Handler实例把消息发送到消息队列(message queue),在主线程里还有一个轮循器(looper)在检查消息对列里有没有新的消息,一旦发现有新的消息,looper就会交给Handler对象处理,

Handler则调用自己的回调函数HandlerMessage来更新UI或者其它操作。

1.3 Handler的作用

调度消息和Runnable对象去被执行;使动作在不同的线程中运行

注:Handler对Message的处理并不是并发的。

1) 一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的。但是如果用不同的Looper则能达到并发的目的

2)Handler能够让你发送和处理消息,以及Runnable对象,每个Handler对象对应唯一的Thread和MessageQueue。

3)当你创建一个Handler对象之后,它就与MessageQueue绑定在一起了

4)当一个应用程序中进程被创建时,它的主线程专门运行消息队列(MessageQueue),去管理顶层的应用程序相关的对象,eg:activity,broadcastReceiver等

综上所述:Handler做了以下几件事

1)运行在某个线程上,共享该线程的消息队列

2)接收消息 、调度消息、派发消息、处理消息

3)实现消息的异步处理

1.4 Handler的作用

 

图1:简单的子线程发送信息给UI线程图例

 

图2:主线程与子线程进行交互的图例

 

从这个流程图中我们可以从中找到几个被用到的类

Message: 就是消息原型,包含消息的描述与数据

MessageQueue: 就是消息队列,存放消息的地方,每个线程最多只能拥有一个MessageQueue

Looper:  MessageQueue的管理者,每个线程只能有一个Looper

Handler: 统领Message.class、MessageQueue.class、Looper.class

 

2. Handler.class源码解析

从官方文档中分析, Handler的主要作用是能够让你发送和处理消息/Runnable对象,每一个Handler对应一个Thread和一个Thread的消息队列,当你创建一个Handler的时候,它就和Thread的消息队列绑定在一起,然后就可以传递消息或者Runnable对象给消息队列

当一个应用程序被创建时,它的主线程专门运行消息队列MessageQueue去管理顶层的应用程序相关的对象,例如:activity、broadcastReceiver等,你可以创建你的Thread,通过主线程的Handler对象与主线程进行交互,发送message或者runnable对象给主线程,交互的方法就是通过handler.post/sendMessage

类中的全局变量

final MessageQueue mQueue;  

    final Looper mLooper;

    final Callback mCallback;

IMessenger mMessenger;

2.1 Handler的构造方法

public Handler() {

public Handler(Callback callback) {

public Handler(Looper looper) {

public Handler(Looper looper, Callback callback) {

publicHandler(boolean async) {

public Handler(Callback callback, boolean async) {

 

在线程中创建Handler对象时,需要做以下工作:

1.获取Thread中的Looper对象交给Handler的成员变量引用维护

2.通过Looper对象获取MessageQueue交给Handler的成员变量引用维护在使用Handler时,需要重写handlerMessage方法(消息处理的方法)

举例:Handler handler = newHandler(){

publicvoid handleMessage(Message msg) {

switch (msg.what) {

case 1:break;

case 2:break;

case 3:break;

default:

break;

}

}

};

 

2.2 Handler对消息的发送

消息发送的两种方式:post和sendMessage

post():针对Runnable对象,Runnable是一个接口,就是一个回调函数(提供了run方法)

sendMessage():针对message对象

 

下面我们来看下代码:

Post:

 

publicfinalbooleanpost(Runnable r){

returnsendMessageDelayed(getPostMessage(r), 0);

}

privatestatic Message getPostMessage(Runnable r) {

        Message m = Message.obtain();

        m.callback = r;

return m;

}

publicfinalbooleansendMessageDelayed(Message msg, longdelayMillis){

if (delayMillis<0) {

delayMillis=0;

}

returnsendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

 

SendMessage :

 

publicfinalboolean sendMessage(Message msg){

return sendMessageDelayed(msg, 0);

}

publicfinalbooleansendMessageDelayed(Message msg, longdelayMillis){

if (delayMillis < 0) {

   delayMillis = 0;}

returnsendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

由上面的代码可以看出,不论是message还是runnable ,处理方式都是类似的

==================================================

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);//将消息插入队列

}

==================================================

2.3  Handler对消息的处理

 public void handleMessage(Message msg) {

    }

public void dispatchMessage(Message msg) {

//首先判断runnable对象

        if (msg.callback != null) {

handleCallback(msg);

        } else {

            if (mCallback != null) {                //整个系统的回调函数

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

    handleMessage(msg);//消息处理

        }

    }

3、代码具体分析

3.1  Message.class

3.1.1 Message.class各属性解析

public int what;// 消息的标示

public int arg1; // 传递简单数据,用这个更比setData更能节省资源

public int arg2;// 同上

public Object obj;// 传递比较复杂的数据

public Messenger replyTo;// 

/*package*/ long when;// 什么时候处理这个消息

/*package*/ Bundle data;// 传递比较复杂的数据

/*package*/ Handler target;//处理消息的目标handler

/*package*/ Runnable callback;// 消息派发时执行Runnable对象

/*package*/Message next;// 使消息形成链表,同时,构建消息池的链表结构

private static Message sPool;// 构建一个消息池

private static intsPoolSize = 0;// 消息池内的消息数量,初始值为0

private static final intMAX_POOL_SIZE = 50;// 消息池的最大数量

 

实际上,Message本身不单纯是一个简单的只包含数据的类,它实际上是一个链式结构的类,也就是说,一个Message本身就是一个消息队列,它通过next将所有消息串联起来。既然Message本身就是消息队列,那MessageQueue又是如何建立消息队列的又是怎么回事?实际上,MessageQueue内部只有一个Message成员,它所要做的工作就是把Message实体串连起来,形成消息链。

3.2 MessagePool消息池原理及代码分析

3.2.1 Message的构造方法

 Message对象可以通过Message.obtain()或者obtainMessage()方法获得(即使Message的构造方法是公开的,也不推荐使用new创建Message);                   

以下列出了3种创建Message的方法:

1.new Message();

2.Message.obtain();

publicstaticMessage obtain() {

synchronized (sPoolSync) {

if (sPool != null) {

  Message m = sPool;

sPool = m.next;

  m.next = null;

sPoolSize--;

return m;

}

}

return new Message();

}

3.handler.obtainMessage()

Public final Message obtainMessage() {

return Message.obtain(this);

}

关于MessagePool消息池

3.2.2为什么要创建消息池

通常消息处理完毕之后,消息基本处于无用状态可以释放回收了,众所周知,频繁的创建对象与释放对象,会增加系统的开销,而Message这种对象就很有可能被频繁的创建,于是乎,有了消息池这个结构

我们将创建的对象在用完之后保存在一个Pool中,当我们下次需要使用对象时,可以不去创建对象,而是从池中取出一个对象重复利用

 

流程图:

 

图3:消息池工作流程图

 

3.2.3 MessagePool的建立

以下省略部分不必要的代码

Looper.class ====>>

Public static voidloop() {

.....................

msg.recycle(); // 处理完的消息调用recycle方法()

}

Message.class ====>>

Public void recycle() {

        clearForRecycle();// 将所有数据清零

synchronized (sPoolSync) {

if (sPoolSize<MAX_POOL_SIZE) {

next = sPool;//结合obtain()理解更清晰

sPool = this;//该对象保存在pool中 

sPoolSize++;// 池内消息数量+1

}

        }

}

3.2、Looper源码解析

Looper介绍:

是MessageQueue的管理者,每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的,每一个Looper对象和一个线程关联,子线程默认是没有Looper对象的,需要通过prepare函数,自己定义一个Looper对象,当创建一个Looper对象时,Looper对象会自动创建一个MessageQueue,当调用Looper.loop方法时,会启动Looper来遍历MessageQueue

个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

 

MainLooper:主线程的Looper

主线程的Looper是Android系统默认给创建的,不需要手动创建, 可以通过Looper.getMainLooper()方法获取主线程的Looper对象

Looper.class代码:

3.2.1 Looper.prepare();方法解析

 public static void prepare() {

prepare(true);

    }

    private static void prepare(boolean quitAllowed) {

        if (sThreadLocal.get() != null) {

            throw new RuntimeException("Only one Looper may be created per thread"); // 一个线程只能有一个Looper,否则报出RuntimeException

        }

sThreadLocal.set(new Looper(quitAllowed));// 保存

}

下面附上ThreadLocal.set()代码

publicvoid set(T value) {

  Thread currentThread = Thread.currentThread();

  Values values = values(currentThread);

  if (values == null) {

    values = initializeValues(currentThread);

  }

  values.put(this, value);

}

prepare()究竟做了什么:将looper保存于一个类似于Map的结构中,key为当前线程,value为当前线程的looper对象

Looper.myLooper(),获取当线程对应的Looper对象

附上Looper.class的几个属性

static final ThreadLocal<Looper>sThreadLocal  = new ThreadLocal<Looper>();

private static Looper sMainLooper;

final MessageQueue mQueue;

下面是ThreadLocal.get()的源代码

/** 

*返回此变量的当前线程的值。如果一个条目 

*还没有为这个线程该变量存在,此方法将 

*创建一个条目,用结果填充值 

*{@link#initialValue()}。 

*@返回变量的调用线程的当前值。 

*/

 

public T get() {

// Optimized for the fast path. 优化的快速路径?

Thread currentThread = Thread.currentThread();

Values values = values(currentThread);

if (values != null) {

Object[] table = values.table;

int index = hash& values.mask;

if (this.reference == table[index]) {

return (T) table[index + 1];

}else {

      values = initializeValues(currentThread);

}

return (T) values.getAfterMiss(this);

}

3.3、ThrealLocal<T>

=======================================

/** 

*实现一个线程局部存储,也就是一个变量,每个线程 

*有其自身的值。所有线程共享相同的{@ ThreadLocal的代码}对象, 

*但每次访问它时,看到一个不同的值,并且由一个所做的更改 

*线程不影响其他线程。实现支持{@ null}值。 

*@看到的java.lang.Thread 

*@作者鲍勃·李 

*/

=======================================

TreadLocal类在JDK5.0支持泛型,类名变为ThreadLocal<T>

ThreadLocal<T>概述

为我们解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。

ThreadLocal其实是一个Thread的局部变量,也许把它命名ThreadLocalVariable更容易让人理解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本

ThreadLocal<T>的接口方法

ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

void set(Object value) ==> JDK5.0之后支持泛型==> void set (T value)

设置当前线程的线程局部变量的值。

public Object get()   ==> JDK5.0之后 ==> public T get()

该方法返回当前线程所对应的线程局部变量 

public void remove()

将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的

是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量

并不是必须的操作,但它可以加快内存回收的速度

protected Object initialValue() ==> JDK5.0之后 ==> protected T initialValue()

返回该线程局部变量的初始值,该方法是一个protected 的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null

实现原理/流程图

当多个Thread对象同时去访问一个Threadlocal对象时,Threadlocal对象只是充当一个Key的角色,而不是变量的储存介质,Threadlocal对象的set()和get()方法所涉及的value是储存于ThrealocalMap中的value,而ThreadlocalMap是每个Thread各自专用的,互补相等的,这就是Threadlocal被多线程同时访问,Threadlocal的值互不干扰的原理

 

图4: ThreadLocal运行流程图

Thread与同步机制比较

应在线程同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量, 这时该变量是多个线程共享的,使用同步机制要求程序慎密的分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等复杂问题,程序设计和编写难度相对较大

而ThreadLocal则从另一个角度来解决多线程的并发访问,ThreadLocal会为每一个线程提供一个独立的线程拷贝,从而隔离了多个线程对数据的访问冲突,因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了,ThreadLocal提供了线程安全的共享对象,在编写多项成代码时,可以把不安全的变量封装进ThreadLocal

Threadlocal小结

ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同

资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用

ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。

为什么要在Looper中使用ThreadLocal

好处很明显,如果用一个全局的HashMap来管理Looper的话,当需要增删改某个Looper对象时,就需要进行同步操作,这大大增加了系统开销,如果有一个ThreadlocalMap保存于本地线程里,需要用的时候直接去取,就可以避免同步带来的低效率问题,所以Threadlocal正好被应用到了一个Thread对应一个Looper中

3.4 Looper.loop();-----------启动消息循环

public static void loop() {

        final Looper me = myLooper(); // 由于是静态方法,所以需要获取当前线程的Looper对象

        if (me == null) {

            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

        }

        final MessageQueue queue = me.mQueue;  //获取当前looper对象绑定的MessageQueue对象

        Binder.clearCallingIdentity(); 

        final long ident = Binder.clearCallingIdentity(); //该方法返回的是当前进程的pid、uid等信息混合后的唯一标示

        for (;;) {   //开始循环

            Message msg = queue.next();  //从消息队列中获取msg

            if (msg == null) {

                return;   //若msg为null,则结束此循环

            }

Printer logging = me.mLogging;

            if (logging != null) {

                logging.println(">>>>> Dispatching to " + msg.target + "" +

                        msg.callback + ": " + msg.what);

}

//若msg不为null,则调用msg.target.dispatchMessage()方法

msg.target.dispatchMessage(msg);  

            if (logging != null) { 

               logging.println("<<<<< Finished to " + msg.target + "" + msg.callback);

            }

         final long newIdent = Binder.clearCallingIdentity();//再次获取一次标示

         if (ident != newIdent) {

                Log.wtf(TAG, "Thread identity 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();// MessagePool回收msg

        }

}

 

3.5、MessageQueue.class源码分析

 

3.5.1 MessageQueue类的介绍:
 用于管理消息链表的类,但其中并不是Java中的Queue,因为通过Message的属性next,就可以看出,Message类本身就算是一个链表结构,而MessageQueue类的作用,就是管理这个链表结构

下面附上一些MessageQueue的部分属性

Message mMessages;// Message实例,代表队列的头元素

private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();// 存放IdleHandler的ArrayList

private IdleHandler[] mPendingIdleHandlers;//是数组版本,后面的代码将把mIdleHandlers的内容拷贝到这个数组中

private boolean mQuiting;// 布尔类型值,判断队列是否在退出状态

3.5.2 IdleHandler接口解析;

IdleHandler接口的作用:

允许用户注册一个回调,当线程将要出去空闲状态时,提前给用户一个回调,用户可以利用这个空闲时间干点其他事情

   public static interface IdleHandler {

  boolean queueIdle();

    }

//一个用于在一个线程里等待更多消息阻塞的接口,当消息队列为null时,等待更多消息,执行这个queueIdle(),如果返回真,则继续保持你的IdlieHandler的活跃状态,下次空闲时仍会再执行这个IdileHandler,如果消息队列里有消息,但是他们的执行时间在当前时间之后,queueIdle也会被调用;如果返回值为false,则remove这个IdlieHandler

添加方法:

  public void addIdleHandler(IdleHandler handler) {

        if (handler == null) {

throw new NullPointerException("Can't add a null IdleHandler");

        }

        synchronized (this) {

            mIdleHandlers.add(handler);

        }

    }

向消息队列中添加一个新的MessageQueue.IdleHandler。当调用IdleHandler.queueIdle()返回false时,此MessageQueue.IdleHandler会自动的从消息队列中移除。

删除方法:

 public void removeIdleHandler(IdleHandler handler) {

        synchronized (this) {

            mIdleHandlers.remove(handler);

        }

}

下面附上一个IdleHandler的使用例子:

Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {

public boolean queueIdle() {

Log.d("Sandy", "queueIdle");

Toast.makeText(MainActivity.this, "主线程空闲了", Toast.LENGTH_SHORT).show();

return false;

}

});

3.5.3 next()方法解析;

 Message next() {

        int pendingIdleHandlerCount = -1; // -1 only during first iteration

        int nextPollTimeoutMillis = 0;// 初始化了两个变量

        for (;;) {

            if (nextPollTimeoutMillis != 0) {

                Binder.flushPendingCommands();}// native方法,,不解

nativePollOnce(mPtr, nextPollTimeoutMillis);

==================================================

//虽然这是一个native方法,但是我们方法名字和下面的代码可以看出,nativePollOnce等待完毕之后,next函数将从mMessages中获取一个Message,也就是说,要让nativePollOnce方法返回,就至少要添加一个Message到消息队列中

==================================================

synchronized (this) {

   // Try to retrieve the next message.  Return if found.

   final long now = SystemClock.uptimeMillis();//获取当前时间

   Message prevMsg = null;//初始化变量为null

   Message msg = mMessages;//获取队列的消息头

   if (msg != null && msg.target == null) {

      do {

        prevMsg = msg;//同时更新prevMsg变量

        msg = msg.next;//如果队列的消息头为null,则获取下一个消息

     } while (msg != null && !msg.isAsynchronous());

   }//直到 msg==null(搜寻到了队列的尾部,表示没有更多的消息)或者 搜寻到一个异步消息

  if (msg != null) {//如果找到了一个消息

      if (now < msg.when) {

nextPollTimeoutMillis=

 (int)Math.min(msg.when-now, Integer.MAX_VALUE);

//当msg到了该处理的时间,也就是说我们找到了消息,则把消息返回 

      } else {

        // Got a message.

        mBlocked = false;

//下面几行代码的大概意思是,设置mBolocked为false,将msg从mMessages队列里取出,并执行msg.next==null、msg.markInUse()操作,如果没有return的话则继续等待(else之后的操作)

      if (prevMsg != null) {

         prevMsg.next = msg.next;

      } else {

         mMessages = msg.next;

      }

      msg.next = null;

      if (false){

 Log.v("MessageQueue", "Returning message: " + msg);

         msg.markInUse();

         return ms ;     //如果获取了一个正常的Message,就会交给Looper进行处理

      } else {

//nativePollOnce方法结束之后,会尝试获取 Message,如果获取不到,就将nextPollTimeoutMillis的值设置为-1,继续等待

nextPollTimeoutMillis = -1;

      }

  if (mQuiting) {//因为没有return,所以检查队列是否要求退出

          dispose();//如果是,则执行dispose()方法

          return null;

      }

//下面既然没有消息要处理,则线程处于空闲状态-->>处理idlerHandler对象

==================================================

//判断mIdleHandlers(ArrayList)是否大于0,如果是就将这里的元素取出,放入mPendingIdleHandlers数组中,并迭代这个数组

==================================================

if (pendingIdleHandlerCount < 0

&& (mMessages == null || now <mMessages.when)){

    pendingIdleHandlerCount = mIdleHandlers.size();

}

if (pendingIdleHandlerCount <= 0) {

// No idle handlers to run.  Loop and wait some more.

mBlocked = true;

continue;

}

if (mPendingIdleHandlers == null) {

mPendingIdleHandlers=new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];

}

mPendingIdleHandlers= mIdleHandlers.toArray(mPendingIdleHandlers);

}

==================================================

遍历mPendingIdleHandlers数组

==================================================

for (int i = 0; i < pendingIdleHandlerCount; i++) {

final IdleHandler idler = mPendingIdleHandlers[i];

mPendingIdleHandlers[i] = null;                 

boolean keep = false;

try {

keep = idler.queueIdle();//根据idler的返回值,决定是否保留这个idleHandler

} catch (Throwable t) {

Log.wtf("MessageQueue", "IdleHandler threw exception", t);

}

if (!keep) {

synchronized (this) {

mIdleHandlers.remove(idler);//根据返回值,处理idler对象

}

}

pendingIdleHandlerCount = 0;

nextPollTimeoutMillis = 0;

}

    }//当线程下次调用nativePollOnce函数的时候,不设置超时时间了,因为很可能在这段时间内,已经有消息加入队列了。

==================================================

3.6 equeueMessage方法解析

消息插入队列

boolean enqueueMessage(Message msg, long when) {

如果msg正在被使用,或者msg对应的handler为空或者队列正在退出状态,均报异常

==================================================

if (msg.isInUse()) {

thrownew AndroidRuntimeException(msg + " This message is already in use.");

        }

if (msg.target == null) {

thrownew AndroidRuntimeException("Message must have a target.");

        }

boolean needWake;

synchronized (this) {

if (mQuiting) {//如果队列正在退出状态,就不能往里插入元素了,则抛出RuntimeException,并return false ,表示插入失败

  RuntimeException e = new RuntimeException(

    msg.target + " sending message to a Handler on a dead thread");

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

returnfalse;

}

==================================================

msg.when = when;//准备工作

Message p = mMessages;//获取队列的头元素

if (p == null || when == 0 || when < p.when) {

msg.next = p;

mMessages = msg;

needWake = mBlocked;
如果队列是空的,或者when==0 或者 插入时间小于p.when,则会把消息插入消息队列的头,那么msg将成为新的队列头元素, 否则插入消息队列尾

} else {

  needWake = mBlocked&& p.target == null&&msg.isAsynchronous();

  Message prev;

for (;;) {

  prev = p;

  p = p.next;

if (p == null || when < p.when) {

break;

}

if (needWake && p.isAsynchronous()) {

    needWake = false;

}

}

msg.next = p; // invariant: p == prev.next

prev.next = msg;

}

}

if (needWake) {

nativeWake(mPtr);

}

return true;

}

0 0
原创粉丝点击