我们在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 null mCallback = callback; // mAsynchronous false mAsynchronous = async; }
我们看下myLooper()方法,
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
sThreadLocal是什么我们看下:
// sThreadLocal.get() will return null unless you"ve called prepare(). static final ThreadLocalsThreadLocal = new ThreadLocal ();
在没有调用Looper的prepare()情况下回返回null,我们看下prepare()方法的实现:
private static void prepare(boolean quitAllowed) { //一个Thread只能有一个Looper绑定 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
现在终于可以看下Looper是构造方法了
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
到这里Handler的mLooper和mQueue就找到出处了
我们看下sendMessage()做了什么:
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } //uptimeMillis() 从开机到现在的毫秒数 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { //looper中创建的queue 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是handler对象 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
这里调用了MessageQueue的enqueueMessae()方法,把我们的msg添加到queue里
我们再来看下Looper.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 final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { //================================================================== // 重点代码在这里 msg.target.dispatchMessage(msg); //================================================================== } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } 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(); } }
重点代码是 msg.target.dispatchMessage(msg);这句代码,msg的target对象实际就是Handler,我们看下Handler的dispatchMessage()方法。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
看到了我们熟悉的handleMessaee()方法
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70227.html
摘要:机制处理的个关键对象线程之间传递的消息,可以携带一些简单的数据供子线程与主线程进行交换数据。解决方法子线程通过发送消息给主线程,让主线程处理消息,进而更新。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 极力推荐文章:欢迎收藏Android 干货分享 showImg(https://...
摘要:在级事件中定义了个鼠标事件,分别是。取消鼠标事件的默认行为还会影响其他事件,因为鼠标事件与其他事件是密不可分的关系。同样的,和支持这个事件。兼容各个浏览器的事件监听对象该对象封装了和级事件的常用事件函数。 概述 鼠标事件是web开发中最常用的一类事件,毕竟鼠标还是最主要的定位设备。在DOM3级事件中定义了9个鼠标事件,分别是:click,dbclick,mousedown,mousee...
阅读 3717·2023-04-25 22:43
阅读 3718·2021-09-06 15:15
阅读 1337·2019-08-30 15:54
阅读 3558·2019-08-30 14:20
阅读 2888·2019-08-29 17:16
阅读 3120·2019-08-29 15:28
阅读 3400·2019-08-29 11:08
阅读 1075·2019-08-28 18:05