您的位置:首页 > 移动开发 > Android开发

Android Handler体系部分源码学习

2016-09-06 20:07 316 查看
先来看一下Handler的基本流程:



(1)先分析第一部分的代码 Looper.prepare():

private static void prepare(boolean quitAllowed) {

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

        throw new RuntimeException("Only one Looper may be created per thread");

    }

    sThreadLocal.set(new Looper(quitAllowed));
}
可以看到就是创建一个Looper对象,然后存入ThreadLocal对象中,同时也就实现了每个线程都有相互独立Looper

(2)Looper.loop()

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {

    final Looper me = myLooper();

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

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

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

loop();开始调用以后就进入了死循环
并且不断获取下一个Message,
再将Message交给它的target的dispatchMessage方法进行处理。

(3)new Handler()

public Handler() {

    this(null, false);

}

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) {

            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 = callback;

    mAsynchronous = async;

}

我们来看看 new Handler()到底做了什么,
其实就是获得当前线程的Looper,使得Handler与Looper进行绑定,这是默认的实现。
同时也有带有Looper的构造函数,这就代表了Handler其实可以绑定其他线程的Looper。

(4)post消息

public final boolean sendMessage(Message msg)

{

    return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)

{

    if (delayMillis < 0) {

        delayMillis = 0;

    }

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

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

可以看到在Handler中最终调用的就是将消息放入消息队列的方法
queue.enqueueMessage(msg, uptimeMillis);

总结:
最后,通过简单的学习几个相关类的源码,我们就可以试着理解为什么平时我们可以用Handler来解决子线程里更新UI的问题了:
(1)首先我们在主线程中 newHandler 绑定到了主线程中的Looper
(2)post出去的消息也就发到了UI线程中Looper的消息队列中
(3)Looper循环处理Message中的消息其实是回调了 Handler中的处理方法
(4)同时Looper是在它绑定的的线程里执行处理方法的,其实就相当于在UI线程中执行了处理代码,也就可以更新UI了。

这样Handler的原理是基本打通了,但是有很多细节还没能深入学习,一部分是因为再往下层涉及到的东西我还没看懂,估计还需要一段时间,所以先把阶段性的成果先放出来
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码 Android 安卓