Handler Looper Message的源码分析

来源:互联网 发布:特别想找个女朋友知乎 编辑:程序博客网 时间:2024/05/21 11:23

1.Handler

通常我们创建Handler都是使用其无参数的构造方法

<span style="font-weight: normal;">public Handler() {//参数1:Callback的接口实现类对象,可以知道直接new Handler()的时候,其成员变量mCallback是等于null的.        this(null, false);    }</span>

方法的官方解释:

Default constructor associates this handler with the {@link Looper} for the current thread.If this thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.


大概的意思就是:

创建Handler是跟当前的线程有关的Looper有关的,如果当前的线程没有Looper,那么该Handler将接受不到消息,并且会抛出一个异常.

查看源码发现,该无参数的构造方法内部是调用了接收2个参数的构造方法:

方法的官方解释:

1.Use the Looper for the current thread with the specified callback interface and set whether the handler should be asynchronous.

2.Handlers are synchronous by default unless this constructor is used to make one that is strictly asynchronous.

3.@param callback The callback interface in which to handle messages, or null.@param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for each Message that is sent to it or  Runnable that is posted to it.

上面3段解释大概的意思就是:

1.使用当前线程的Looper和callback接口并设置改handler是否是异步的.

2.Handler创建的时候默认是同步的,除非通过构造方法设置为异步的

3.对于传入的2个参数的解释,参数callback接口是用于处理消息的,也可以传入null;参数async是用来控制该Handler是否是异步,如果是true,那么handler里面会调用Message的setAsynchronous(boolean)方法,表示Handler处理异步消息,相当于sendMessage的方式处理,如果是false,则Handler处理的是同步消息,相对于postRunnable的方式处理.

源码分析:

final MessageQueue mQueue;    final Looper mLooper;    final Callback mCallback;    final boolean mAsynchronous;    public Handler(Callback callback, boolean async) {        if (FIND_POTENTIAL_LEAKS) {            final Class<? extends Handler> klass = getClass();            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&                    (klass.getModifiers() & Modifier.STATIC) == 0) {//大概的意思就是创建Handler的匿名内部类,成员类,局部类的时候会给出下面log的提示                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +                    klass.getCanonicalName());            }        }//获取当前线程的Looper对象        mLooper = Looper.myLooper();        if (mLooper == null) {//当前线程的Looper对象为null,抛出异常,该异常就是在子线程创建Handler时,没有调用Looper.prepare()造成的.            throw new RuntimeException(                "Can't create handler inside thread that has not called Looper.prepare()");        }//通过Looper对象获取MessageQueue消息队列        mQueue = mLooper.mQueue;//记录传递进来的callback接口,注意这里的Callback接口是定义在Handler类内部的.        mCallback = callback;//记录是否是异步        mAsynchronous = async;    }Handler定义的内部接口/**     * 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 //如果没有进一步的消息处理,就可以直接返回True     */    public interface Callback {        public boolean handleMessage(Message msg);    }

分析上面的源码可以发现,在new Handler的时候,内部会得到一个Looper对象,以及该Looper的MessageQueue对象.同时提到了 "Can't create handler inside thread that has not called Looper.prepare()");这个异常.
带着上面的疑问,继续查看Looper的源码:

2.Looper
Looper的源码比较短,这里直接贴出源码

public final class Looper {      private static final String TAG = "Looper";    // sThreadLocal.get() will return null unless you've called prepare().    //默认ThreadLocal.get()会返回null,除非调用了prepare()方法.    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();    //主线程的Looperprivate static Looper sMainLooper;  // guarded by Looper.class    //消息队列    final MessageQueue mQueue;    //当前线程    final Thread mThread;     //log输出对象    private Printer mLogging;     /** Initialize the current thread as a looper.      * This gives you a chance to create handlers that then reference      * this looper, before actually starting the loop. Be sure to call      * {@link #loop()} after calling this method, and end it by calling      * {@link #quit()}.      */    //初始化当前线程的Looper对象    public static void prepare() {        prepare(true); //true 退出允许    }    private static void prepare(boolean quitAllowed) {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }//创建Looper对象,绑定到当前线程中.        sThreadLocal.set(new Looper(quitAllowed));    }    /**     * Initialize the current thread as a looper, marking it as an     * application's main looper. The main looper for your application     * is created by the Android environment, so you should never need     * to call this function yourself.  See also: {@link #prepare()}     */    //初始化主线程的Looper对象,由android系统调用.    public static void prepareMainLooper() {        prepare(false);        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }    //记录主线程的Looper            sMainLooper = myLooper();        }    }    /**     * Returns the application's main looper, which lives in the main thread of the application.     */    //获取主线程的Looper    public static Looper getMainLooper() {        synchronized (Looper.class) {            return sMainLooper;        }    }    /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    //轮询MessageQueue中的Message    public static void loop() {//获取当前线程的Looper        final Looper me = myLooper();        if (me == null) {//如果Looper的prepare()方法没有调用的话,那么myLooper()方法返回的当前线程的Looper将等于null,将会抛出下面的异常;主线程的Looper是由系统去调用prepare()方法的,所以在主线程使用Handler的时候无需手动调用Looper.prepare();            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }//拿到当前Looper的MessageQue对象        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.//这2行表示没有看懂,不影响阅读        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        for (;;) {    //这里是死循环,从MessageQueue中遍历所有的Message对象            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    //打印log            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }    //获取Message所关联的target,这里的target其实就是Handler对象,调用对应的Handler对象的dispatchMessage方法,将消息传递给Handler去处理            msg.target.dispatchMessage(msg);    //以下都是处理log,忽略            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.recycleUnchecked();        }    }    /**     * Return the Looper object associated with the current thread.  Returns     * null if the calling thread is not associated with a Looper.       返回与当前线程相关Looper对象,如果返回null,则说明当前线程没有关联Looper     */    public static @Nullable Looper myLooper() {        return sThreadLocal.get();    }    /**     * Return the {@link MessageQueue} object associated with the current     * thread.  This must be called from a thread running a Looper, or a     * NullPointerException will be thrown.      返回与当前线程相关的MessageQueue对象,这个必须在Looper中运行的线程中调用,否则会报空指针异常     */    public static @NonNull MessageQueue myQueue() {        return myLooper().mQueue;    }    //私有的构造方法,用于初始化消息队列和获取当前线程对象.    private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }    /**     * Returns true if the current thread is this looper's thread.       判断当前的线程是否是Looper所关联的线程     */    public boolean isCurrentThread() {        return Thread.currentThread() == mThread;    }   ....}

在分析Looper源码的时候,提到一行代码msg.target.dispatchMessage(msg);这行代码很重要,正是因为这行代码,我们通过Handler的发送消息的时候,对应的消息才会回传到Handler的handleMessage方法中,因此我们才可以在handleMessage中去处理Handler发送的消息.
那么,如何可以证明target就是我们发送对应消息的Handler对象呢?
要查明真相,最直接的办法就是找到Handler类的sendMessage方法.

/**     * Pushes a message onto the end of the message queue after all pending messages     * before the current time. It will be received 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.     */     //大概意思就是sendMessage发送的消息都会被放置到消息队列的最底部,并且最后会回传到handleMessage方法,该方法返回true则表示消息发送成功,否则失败.    public final boolean sendMessage(Message msg) {        //继续往下调用sendMessageDelayed方法,该方法是一个延时发送消息的方法,这里传递0表示马上发送.        return sendMessageDelayed(msg, 0);    }

接着走..

public final boolean sendMessageDelayed(Message msg, long delayMillis) {        if (delayMillis < 0) {            delayMillis = 0;        }        //继续往下调用sendMessageAtTime,功能是一样的,名字不同而已.        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }

接着走..

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {//判断此时的Looper的MessageQueue是否为null,是者打印警告log        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }//继续往下调用enqueueMessage        return enqueueMessage(queue, msg, uptimeMillis);    }

接着走..

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {//哈哈,重要找到看到真相了.this就是当前Handler,也就是说我们通过Handler调用sendMessage,发送我们所传递进来的Message的时候,该Message对象会将当前发送消息的Handler对象保存到target变量中.        msg.target = this;        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }

通过上面大费周章,我们终于知道了 msg.target.dispatchMessage(msg);这行代码的target对象其实就是Handler对象,那么如何证明dispatchMessage方法就是用来回传消息的呢?
同样,继续查看Handler的dispatchMessage方法

/**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {           //这里的msg.callback,其实就是Message内部引用的Runnable接口,如果不为null,则会回调Runnable的run方法            handleCallback(msg);        } else {            if (mCallback != null) {    //mCallback就是Handler内部定义的Callback接口,上面有提到.这里是回调Callback接口的handleMessage方法,其实现类就可以获取到对应的Message对象了.                if (mCallback.handleMessage(msg)) {//如果Callback的handleMessage方法返回true,那么dispatchMessage方法将结束,意味着下面的Handler的handleMessage方法将不被回调.                    return;                }            }          //如果mCallback==null,或者Callback的handleMessage方法返回false的话,Handler的handleMessage才可以接受到消息.通过Handler的无参构造方法创建Handler的话mCallback就是等于null的.因此我们重写Handler的handleMessage方法就可以接收到我们发送的Message对象            handleMessage(msg);        }    }private static void handleCallback(Message message) {        message.callback.run();    }

3.Message
继续分析下Message的源码,查看Message类可以发现,其实Message就是一个实体Bean,这里主要看看Message的创建一共有几种方式

public final class Message implements Parcelable {    //创建Message的方法1    public static Message obtain() {        synchronized (sPoolSync) {            if (sPool != null) {                Message m = sPool;                sPool = m.next;                m.next = null;                m.flags = 0; // clear in-use flag                sPoolSize--;                return m;            }        }        return new Message();    }    //创建Message的方法2    public static Message obtain(Message orig) {        Message m = obtain();        m.what = orig.what;        m.arg1 = orig.arg1;        m.arg2 = orig.arg2;        m.obj = orig.obj;        m.replyTo = orig.replyTo;        m.sendingUid = orig.sendingUid;        if (orig.data != null) {            m.data = new Bundle(orig.data);        }        m.target = orig.target;        m.callback = orig.callback;        return m;    }    //创建Message的方法3    public static Message obtain(Handler h) {        Message m = obtain();        m.target = h;        return m;    }    //创建Message的方法4    public static Message obtain(Handler h, Runnable callback) {        Message m = obtain();        m.target = h;        m.callback = callback;        return m;    }    //创建Message的方法5    public static Message obtain(Handler h, int what) {        Message m = obtain();        m.target = h;        m.what = what;        return m;    }    //创建Message的方法6    public static Message obtain(Handler h, int what, Object obj) {        Message m = obtain();        m.target = h;        m.what = what;        m.obj = obj;        return m;    }    //创建Message的方法7    public static Message obtain(Handler h, int what, int arg1, int arg2) {        Message m = obtain();        m.target = h;        m.what = what;        m.arg1 = arg1;        m.arg2 = arg2;        return m;    }    //创建Message的方法8    public static Message obtain(Handler h, int what,             int arg1, int arg2, Object obj) {        Message m = obtain();        m.target = h;        m.what = what;        m.arg1 = arg1;        m.arg2 = arg2;        m.obj = obj;        return m;    }    //创建Message的方法9(无参构造方法)    public Message() {    }    //获取Message中保存的目标Handler    public Handler getTarget() {        return target;    }    //返回Message中保存的Runnable的引用    public Runnable getCallback() {        return callback;    }//获取Message的Bundle对象,如果Bundle为null,则会放回一个新的Bundle对象    public Bundle getData() {        if (data == null) {            data = new Bundle();        }        return data;    }    //获取Message保存的Bundle    public Bundle peekData() {        return data;    }    //将Bundle保存到Message中    public void setData(Bundle data) {        this.data = data;    }    //将消息发送给目标Handler    public void sendToTarget() {        target.sendMessage(this);    }    //判断消息是否是异步的    public boolean isAsynchronous() {        return (flags & FLAG_ASYNCHRONOUS) != 0;    }    //设置消息十分是异步的    public void setAsynchronous(boolean async) {        if (async) {            flags |= FLAG_ASYNCHRONOUS;        } else {            flags &= ~FLAG_ASYNCHRONOUS;        }    }       //后面2个就是toString方法    @Override    public String toString() {        return toString(SystemClock.uptimeMillis());    }    String toString(long now) {        StringBuilder b = new StringBuilder();        b.append("{ when=");        TimeUtils.formatDuration(when - now, b);        if (target != null) {            if (callback != null) {                b.append(" callback=");                b.append(callback.getClass().getName());            } else {                b.append(" what=");                b.append(what);            }            if (arg1 != 0) {                b.append(" arg1=");                b.append(arg1);            }            if (arg2 != 0) {                b.append(" arg2=");                b.append(arg2);            }            if (obj != null) {                b.append(" obj=");                b.append(obj);            }            b.append(" target=");            b.append(target.getClass().getName());        } else {            b.append(" barrier=");            b.append(arg1);        }        b.append(" }");        return b.toString();    }}

分析Message源码,一共有9种方式创建Message对象,除了无参构造方法和obtain()创建的Message对象是不会保存Handler到target变量的,其他7中方式都是有保存的.


总结:
通过上面的Handler,Looper,Message的源码分析,大概的结论是:

1.Handler通过发送和处理Message

2.Looper通过轮询MessageQueue无限循环轮询Message,同时将Message回传给对应的Handler处理

3.创建Handler必须要调用Looper.prepare()方法去初始化Looper,否则将报异常,主线程的Looper是由android系统去调用Looper.prepare()的;

4.Looper的loop()方法将是开启消息轮询的关键方法,非UI线程必须手动调用..




0 0
原创粉丝点击