内容简介:该类实现了Parcelable接口,你可以把它看作一个数据类
Handler允许你发送和处理Message,以及和线程相关联的Runnable对象。每一个Handler实例都与一个线程及该线程的MessageQueue相关联。既当你创建一个Handler时,该Handler必须绑定一个线程以及该线程的消息队列,一旦它被创建,它能把messages和runnables传送到message queue,并在它们从message queue中出来的时候执行它们。
Handler主要有两个主要用途:
- 在未来的某个时间点调度messages和runnables的执行
- 将要在不同线程上执行的操作加入队列
当你的应用程序被创建出来的时候,主线程会专门运行一个message queue来管理最顶级的应用对象(如activities, broadcast receivers,等等)以及它们创建的任何其它窗口。你可以创建你自己的线程,通过Handler来与主线程建立联系
2.源码分析
2.1 MessageQueue-消息队列
MessageQueue是一个通过Looper分发它持有的消息列表的低层级类。Messages没有直接添加到MessageQueue中,而是通过与Looper相关联的Handler对象。
- Message-消息
该类实现了Parcelable接口,你可以把它看作一个数据类
** * * Defines a message containing a description and arbitrary data object that can be * sent to a {@link Handler}. This object contains two extra int fields and an * extra object field that allow you to not do allocations in many cases. * 定义包含描述和任意数据对象的消息 * 发送到Handler。这个对象包含两个额外的int字段和一个 * 额外的对象字段,允许您在很多情况下不进行分配。 * <p class="note">While the constructor of Message is public, the best way to get * one of these is to call {@link #obtain Message.obtain()} or one of the * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull * them from a pool of recycled objects.</p> * 注意:不要直接使用New Message()创建Message对象,最好的方式是通过Handler.obtainMessage() * 方法,它会从对象回收池中拉取该消息对象 */ public final class Message implements Parcelable { /** @hide */ public static final Object sPoolSync = new Object(); /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. * 从全局池返回一个新的消息实例。让我们在很多情况下避免分配新对象。 */ 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(); } ** * Same as {@link #obtain()}, but sets the value for the target member on the Message returned. * 与obtain()相同,但在返回的消息上设置目标成员的值。 * @return A Message object from the global pool. * 返回来自全局池的消息对象 */ public static Message obtain(Handler h) { Message m = obtain(); m.target = h;//接收传递过来的Handler return m; } } 复制代码
2.2 Looper-消息轮询器
Looper用于为线程轮询messages。线程默认是没有与之相关联的Lopper,我们必须通过Looper.prepare()方法去创建它。示例:
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } } 复制代码
- ThreadLocal提供线程的局部变量,通过它访问线程独立初始化变量的副本。即Looper通过ThreadLocal类来与当前线程进行交互
//私用构造方法 //quitAllowed是否允许退出 private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed);//实例化消息队列 mThread = Thread.currentThread();//获取当前线程 } /** 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 * 在它准备轮询之前,给你一个时机点去创建一个Handler并引用它 * 调用该方法后一定记得Looper.loop()方法,并结束的时候调用Looper.quit()方法退出 */ public static void prepare() { prepare(true); } // sThreadLocal.get() will return null unless you have called prepare(). //必须先调用Looper.prepare()方法,否则返回空 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { //每一个线程只能有唯一的一个looper if (sThreadLocal.get() != null) {//不为空抛出异常 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));//设置Looper } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. * 返回与当前线程关联的looper */ public static @Nullable Looper myLooper() { return sThreadLocal.get(); } /** * 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();//获取looper if (me == null) {//为空则抛出异常 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;//获取looper的消息队列 // 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(); // Allow overriding a threshold with a system prop. e.g. // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start' final int thresholdOverride = SystemProperties.getInt("log.looper." + Process.myUid() + "." + Thread.currentThread().getName() + ".slow", 0); boolean slowDeliveryDetected = false; for (;;) {//无限轮询 Message msg = queue.next(); // might block if (msg == null) { //没有message则不往下执行 // No message indicates that the message queue is quitting. return; } ***省略代码*** final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0; final long dispatchEnd; try { msg.target.dispatchMessage(msg);//调用Handler的dispatchMessage(msg)方法 dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } //回收可能正在使用的消息。 //在处理消息队列时,MessageQueue和Looper在内部使用。 msg.recycleUnchecked(); } } //sThreadLocal.get() public T get() { Thread t = Thread.currentThread();//通过Thread的静态方法获取当前的线程 //ThreadLocalMap是一个定制的HashMap(),仅适用于维护线程局部值,每一个线程都持有一个ThreadLocalMap对象 ThreadLocalMap map = getMap(t);//传入当前线程获取当前线程的ThreadLocalMap对象 -------------------------------------------------------------------------------————————————— ThreadLocalMap getMap(Thread t) { return t.threadLocals; } -------------------------------------------------------------------------------————————————— if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } 复制代码
2.3 Handler
2.3.1 创建Handler对象
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. * 如果你不想通过继承Handler来实现,你必须实现Callback接口 */ public interface Callback { /** * @param msg A {@link android.os.Message Message} object * @return True if no further handling is desired */ public boolean handleMessage(Message msg); } //默认构成器 //如果该Handler所绑定的线程没有looper,它将收不到任何messages,并且会抛出异常 public Handler() { this(null, false); } //默认构造器的Callback为空,所以当我们通过new Handler()来创建实例时, //我们必须重写Handler的handleMessage(Message msg)方法,即: companion object {//注意写成静态内部类的形式,避免内存泄漏 private class MyHandler :Handler(){ override fun handleMessage(msg: Message?) { super.handleMessage(msg) } } } -------------------------------------------------------------------------------————————————— //主动实现Callback接口,来创建Handler实例 public Handler(Callback callback) { this(callback, false); } companion object { private val mHandler1:Handler = Handler(object :Handler.Callback{ override fun handleMessage(msg: Message?): Boolean { return true } }) 或 private val mHandler2:Handler = Handler(Handler.Callback { true }) } -------------------------------------------------------------------------------————————————— /** * Use the provided {@link Looper} instead of the default one. * * @param looper The looper, must not be null. * //不使用默认的looper */ public Handler(Looper looper) { this(looper, null, false); } //之前我看到某些前辈是通过下面这种方式来创建Handler实例,通过传递主线程的looper //但这是没必要的,Handler默认就是使用主线程的looper(下面会分析) //并且源码注释也说了,使用你自己的提供的looper而不是默认的 private val mHandler:Handler = object :Handler(Looper.getMainLooper()){ override fun handleMessage(msg: Message?) { super.handleMessage(msg) } } -------------------------------------------------------------------------------————————————— //该构造同上,如果你不想重写handleMessage(msg: Message?)方法,那么你就重写Callback接口 public Handler(Looper looper, Callback callback) { this(looper, callback, false); } //是否需要异步处理messages,默认是异步的 public Handler(boolean async) { this(null, async); } //自己提供looper,实现Callback接口,决定是否异步 public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } -------------------------------------------------------------------------------————————————— /* * Set this flag to true to detect anonymous, local or member classes * that extend this Handler class and that are not static. These kind * of classes can potentially create leaks. * 将此标志设置为true以检测匿名类、本地类或成员类 * 继承了Handler不是静态的,可能存在内存泄漏 */ private static final boolean FIND_POTENTIAL_LEAKS = false; //通过Handler()、Handler(Callback callback)、Handler(boolean async) //都会调用该构造器 public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) {//检查可能存在的内存泄漏,默认是false 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();//获取looper if (mLooper == null) {//如果为空抛出异常 throw new RuntimeException( "Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;//获取Looper中的消息队列 mCallback = callback; mAsynchronous = async; } private static void handleCallback(Message message) { message.callback.run();//执行Message持有的Runnable } /** * Handle system messages here. * 处理系统Messages */ public void dispatchMessage(Message msg) { if (msg.callback != null) {//如果Message的Runnable不为空 handleCallback(msg);调用Handler的handleMessage(msg)方法处理Message } else { if (mCallback != null) {//如果Handler的Callback不为空 if (mCallback.handleMessage(msg)) {//调用Callback的handleMessage(msg)方法 return; } } //否则调用Handler的handleMessage(msg)方法 handleMessage(msg); } } 复制代码
2.3.2 创建Message对象
public final Message obtainMessage() { return Message.obtain(this); } public final Message obtainMessage(int what) { return Message.obtain(this, what); } public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } public final Message obtainMessage(int what, int arg1, int arg2) { return Message.obtain(this, what, arg1, arg2); } public final Message obtainMessage(int what, int arg1, int arg2, Object obj) { return Message.obtain(this, what, arg1, arg2, obj); } 复制代码
2.3.3 发送Message
/** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * 将Runnable添加到消息队列中。 * runnable将在此Handler所在的线程上运行。 * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. * Runnable成功添加到消息队列中返回ture,失败返回false */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain();创建Message对象 m.callback = r;把Runnale传递给Message return m; } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) {//延迟时间小于0,则置为0 delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } //延迟发送 public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postDelayed(Runnable r, Object token, long delayMillis) { return sendMessageDelayed(getPostMessage(r, token), delayMillis); } 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;//把当前的Handler传递给Message的Handler if (mAsynchronous) {//是否异步 msg.setAsynchronous(true); } //最终调用MessageQueue的enqueueMessage方法 return queue.enqueueMessage(msg, uptimeMillis); } MessageQueue: boolean enqueueMessage(Message msg, long when) { if (msg.target == null) {//Message的Handler为空,抛出异常 throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) {//Message正在使用,抛出异常 throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) {//判断是否退出 IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle();//回收Message return false; } msg.markInUse();设置Message是否正在使用的Flag msg.when = when; Message p = mMessages; boolean needWake;//是否需要唤醒 if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; needWake = mBlocked; } else { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. //插入到队列的中间。通常我们不需要唤醒 //启动消息队列,除非队列头部有阻碍 //消息是队列中最早的异步消息。 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; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
html转js在线工具
html转js在线工具
HEX CMYK 转换工具
HEX CMYK 互转工具