剖析Android-Handler机制流程

来源:互联网 发布:java se深入浅出 编辑:程序博客网 时间:2024/05/29 14:18

1.Message:消息实现Parcelable以便在进程间传输数据,包含消息标志,以及要传输的消息类型,一般是以Bundle来进行数据的传输,当然Message也定义了两个额外的int和一个Object来进行。

2.MessageQueue:消息队列,存放消息的容器,已FIFO(先进先出)算法来存取消息

3.Handler:处理者,关联一个线程和一个MessageQueue队列,负责Message对象的发送和处理,我们可以重写handleMessage回调接口方法来对Message对象进行处理和更新UI组件

4:Looper:消息泵,循环的从MessageQueue消息队列中读取消息,调用HandledispatchMessage来处理消息

我们用一个例子来分析Handler机制的运转流程

我们一般使用Handler的使用是一般是这样写的在MainActivity中我们声明一个Handler对象并重写其handleMessage回调方法来接收LooperMessageQueue消息队列中读取的Message消息并更新UI组件。

Handler mHandler = new Handler(){

 

@Override

public void handleMessage(Message msg) {

/**

 * 接收消息并处理

 * switch(msg.what){

 * case xx:

 * break;

 * }

 */

super.handleMessage(msg);

}

};

在线程中我们一般是这样使用Handler发送消息给主线程的

mHandler.sendMessage(mHandler.obtainMessage(1));

现在我就来带大家从源码的角度来分析下Handler的流程,从而使大家对Handler的机制有个比较清楚的了解。

首先,追踪mHadnler.sendMessage(mHandler.obtainMessage(1))方法,发现其Handler源码是函数是

   public final boolean sendMessage(Message msg)

    {

        return sendMessageDelayed(msg, 0);

}

继续追踪sendMessageDelayed(Message msg, long delayMillis)函数

 public final boolean sendMessageDelayed(Message msg, long delayMillis)

    {

        if (delayMillis < 0) {

            delayMillis = 0;

        }

        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//在当前时间delayMillis

//毫秒后push消息到MessageQueue队列中

}

继续追踪sendMessageAtTime(Message msg, long uptimeMillis)函数:

 public boolean sendMessageAtTime(Message msg, long uptimeMillis)

    {

        boolean sent = false;

        MessageQueue queue = mQueue;//得到当前的消息队列

        if (queue != null) {

            msg.target = this;//记住当前的Handler

            sent = queue.enqueueMessage(msg, uptimeMillis);//交由MessageQueue队列对Message对象进行处理

        }

        else {

            RuntimeException e = new RuntimeException(

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

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

        }

        return sent;

    }

这里我们要明白MessageQueue queue = mQueue;这个mQueue对象是哪里来的,又是什么时候创建的,这时我们追踪mQueue对象,我们可以发现当我们创建Handler对象时对它进行赋值的:

  public Handler() {

        if (FIND_POTENTIAL_LEAKS) {

            final Class<? extends Handler> klass = getClass();

            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

                    (klass.getModifiers() & Modifier.STATIC) == 0) {

                Log.w(TAG"The following Handler class should be static or leaks might occur: " +

                    klass.getCanonicalName());

            }

        }

 

        mLooper = Looper.myLooper();

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()");

        }

        mQueue = mLooper.mQueue;

        mCallback = null;

    }

Handler类提供的几个构造函数里都有着这句语句,来对mQueue 进行赋值

        mQueue = mLooper.mQueue;

这时我们追踪mLooper时可以发现,其mLooper是一个Looper对象,这时我们去追踪Looper类对象,发现Looper类是这样描述的:

  * Class used to run a message loop for a thread.  Threads by default do

  * not have a message loop associated with them; to create one, call

  * {@link #prepare} in the thread that is to run the loop, and then

  * {@link #loop} to have it process messages until the loop is stopped.

意思就是为线程创建一个消息循环,循环的读取消息,直到停止循环

到这个,我们就可以下个结论:Handler的消息是由Looper来进行循环读取的?结论真是这样吗?

我们查看Looper源码的时候,发现Looper是通过prepare来初始化当前线程的消息泵,并将LooperHandler进行关联,然后通过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;//关联消息队列

 

        // Make sure the identity of this thread is that of the local process,

        // and keep track of what that identity token actually is.

        Binder.clearCallingIdentity();

        final long ident = Binder.clearCallingIdentity();//复位IPC的当前线程的身份标识

 

        for (;;) {//循环读取消息

            Message msg = queue.next(); // might block

            if (msg == null) {

                // No message indicates that the message queue is quitting.

                return;

            }

 

            // This must be in a local variable, 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);

            }

 

            msg.target.dispatchMessage(msg);//

msg.taget是什么呢?通过前面的Handler分析:

msg.target = this;//记住当前的Handler可以发现msg.tagetHandler对象(设计Handler的人既然用msg来记住Handler,高),所以说这句话就是交由HandlerdispatchMessage函数去处理消息

 

            if (logging != null) {

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

            }

 

            // Make sure that during the course of dispatching the

            // identity of the thread wasn't corrupted.

            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();

        }

    }

 

Ok通过分析loop函数源码,我们发现,Handler的消息确实是通过Looper来循环读取,并交于HandlerdispatchMessage来进行处理。细心的同学可能会发现,loop源码中有句语句是讲looperMessageQueue进行关联的语句,那就是:

final MessageQueue queue = me.mQueue;//关联消息队列的,这时,我们就要有个疑问了,我们什么时候Looper对象和MessageQueue 关联起来的,我们追踪mQueue发现这样一个方法

    private Looper(boolean quitAllowed) {

        mQueue = new MessageQueue(quitAllowed);

        mRun = true;

        mThread = Thread.currentThread();

}

这里发现是在Looper的构造函数进行对MessageQueue对消息队列进行创建,当然这里也可以发现Looper的构造函数是个private的,也就是说,此Looper类被设计成一个单例模式,已确保一个线程只有一个Looper来对MessageQueue进行循环的读取消息的。我们在查看下Looper类的定义发现:

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

    private static Looper sMainLooper;  // guarded by Looper.class

 

    final MessageQueue mQueue;

    final Thread mThread;

    volatile boolean mRun;

 

private Printer mLogging;

 

结合前面的分析,我们可以下个定义,Looper在维护着当前线程的MessageQueue的消息队列,通过loop函数对MessageQueue队列循环的读取消息,并交于Handler(通过Message.target来获取)的dispatchMessage函数进行处理,所以现在我们就清楚了Message,MessageQueue,HandlerLooper之间的关系,现在的我们只是还差一步,就是我们为什么重写handleMessage就可以来接收消息,对消息进行处理呢?这时,我们就分析HandlerdispatchMessage方法:

    public void dispatchMessage(Message msg) {

        if (msg.callback != null) {//MessageRunnable对象是否存在,存在就交于handleCallback函数处理

            handleCallback(msg);

        } else {

            if (mCallback != null) {//mCallback 不等于空,

查看源码可以得知mCallback 为 public interface Callback {

        public boolean handleMessage(Message msg);

    }Callback 接口对象

                if (mCallback.handleMessage(msg)) {//交于mCallback 的回调函数处理

                    return;

                }

            }

            handleMessage(msg);//交于handleMessage函数处理,查看Handler可以发现其源码提供了一个handleMessage函数的空实现方法    

public void handleMessage(Message msg) {

    }所以说,只要我们在创建Handler对象的时候,重写了handleMessage方法,我们就可以接收到Message消息,哈哈,现在我们终于知道为什么我们可以在handleMessage函数中接收Message对象了

        }

    }

到现在为止,我们就把MessageMessageQueue,Handler,Looper分析完了,相信大家对Handler的机制应该有个比较清楚的认识了,这里我给Handler机制来下个定义:通过Handlerpush消息到MessageQueue,Looper对象来循环读取MessageQueue消息队列,取得Message对象,通过Message对象的Handler对象的dispatchMessage方法来向Hanlder传递Message消息

0 0
原创粉丝点击