Handler源码解析

Handler

标签(空格分隔): 源码解析 Handler


看了一下,总行数933行,简称百行码;
然后缩减一下注释换行什么的:

public class Handler {
    
    private static final boolean FIND_POTENTIAL_LEAKS = false;
    private static final String TAG = "Handler";
    //指定了一个主线程的Handler
    private static Handler MAIN_THREAD_HANDLER = null;

    //定义一个回调接口,用于构建Handler传入的参数
    public interface Callback {
        public boolean handleMessage(Message msg);
    }
    
    //常规调用的回调,在这里处理我们的回调逻辑,一般用于UI的更新
    public void handleMessage(Message msg) {
    }
    
    /**
     *在MessageQueue中分发消息的时候的调用api
     *从代码可以看出,一共有三种分发方式,取决于调用定义的不同
     *1、new Handler().post(Runnable r);
     *2、new Handler(Callback callback) 
     *3、最普通的默认调用
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
            	//这个mCallback是整个Handler全局的(一个Handler只有一个),可以在这里做一些统一的操作,只要不拦截就行
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    /**
    *构造函数还蛮多的,最终调用还是两个构造
    *Handler(Callback callback, boolean async)和
    *Handler(Looper looper, Callback callback, boolean async) 
    *他们的区别就是是否指定了Looper
    */
    public Handler() {
        this(null, false);
    }
    public Handler(Callback callback) {
        this(callback, false);
    }
    public Handler(Looper looper) {
        this(looper, null, false);
    }
    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
    public Handler(boolean async) {
        this(null, async);
    }

    public Handler(Callback callback, boolean async) {
        //FIND_POTENTIAL_LEAKS这个标签始终为false(定义的时候默认为false,这里是唯一调用)
        //这个标签就是下面代码的检测是否为会内存溢出的定义类,当我们定义一个成员内部类时编译器给出的warn的警告差不多;这里大概就是Google程序员用来调试的标签,并没有对外开放使用。
        if (FIND_POTENTIAL_LEAKS) {
            //取得当前Handler的getClass(匿名或者继承重写的)
            final Class<? extends Handler> klass = getClass();
            //isAnonymousClass:是否匿名类
            //isMemberClass:是否是成员类
            //isLocalClass:是否局部类
            //(klass.getModifiers() & Modifier.STATIC) == 0:是否修饰符为static
            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());
            }
        }
        //获取Looper;Looper实例化了一个对象并扔到了线程本地变量里,在调用Looper.prepare()的时候实例化的,同时在Looper实例化的时候,初始化了一个MessageQueue和当前线程;
        //这里就反馈了一个问题,那就是当前线程中,在线程本地变量中只保存了一个Looper的实例化对象,所以MessageQueue也只有一个,因为只允许有一个Looper的实例,所以Looper.prepare()只准调用一次,不然就在当前线程中二次实例化Looper和MessageQueue,这里明确禁止了;
        mLooper = Looper.myLooper();
        //没有实例化Looper和MessageQueue,抛出异常将要Looper.prepare()
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //去除Looper实例化的时候创建的MessageQueue对象
        mQueue = mLooper.mQueue;
        //对mCallback进行赋值
        mCallback = callback;
        //赋值操作
        mAsynchronous = async;
    }

    //全部是赋值操作
    public Handler(Looper looper, Callback callback, boolean async) {
        //指定某个线程的Looper,剩下的赋值同理
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

    //指定Looper创建Handler对象
    @NonNull
    public static Handler createAsync(@NonNull Looper looper) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        return new Handler(looper, null, true);
    }

    //指定Looper和Callback构建Handler
    @NonNull
    public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        if (callback == null) throw new NullPointerException("callback must not be null");
        return new Handler(looper, callback, true);
    }

    //创建一个基于主线程的Handler
    //为hide方法,不对外暴露API
    @NonNull
    public static Handler getMain() {
        if (MAIN_THREAD_HANDLER == null) {
            MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
        }
        return MAIN_THREAD_HANDLER;
    }

    //获取创建的主线程Handler
    //为hide方法,不对外暴露API
    @NonNull
    public static Handler mainIfNull(@Nullable Handler handler) {
        return handler == null ? getMain() : handler;
    }

    //打印消息栈
    public String getTraceName(Message message) {
        final StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName()).append(": ");
        if (message.callback != null) {
            sb.append(message.callback.getClass().getName());
        } else {
            sb.append("#").append(message.what);
        }
        return sb.toString();
    }

    //获取消息名称
    public String getMessageName(Message message) {
        if (message.callback != null) {
            return message.callback.getClass().getName();
        }
        return "0x" + Integer.toHexString(message.what);
    }

    //从消息池中获取一个Message,省去创建对象的开销,消息池最多容纳50个Message
    public final Message obtainMessage()
    {
        return Message.obtain(this);
    }

    //从消息池中取出一个Message,并指定标签what
    public final Message obtainMessage(int what)
    {
        return Message.obtain(this, what);
    }
    
    //消息池取Message,指定标签what和要传递的对象obj
    public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }

    //消息池取Message,指定标签what和两个额外的参数arg1、arg2
    public final Message obtainMessage(int what, int arg1, int arg2)
    {
        return Message.obtain(this, what, arg1, arg2);
    }
    
    //同理,以上都是省却创建Message的开销而从消息池中取出一个Message对象,然后根据需求添加参数
    public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
    {
        return Message.obtain(this, what, arg1, arg2, obj);
    }

    //扔出一个runnable,内部会将这个runnable赋值到Message的callback属性值上
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    
    //指定时间扔出一个Runnable
    public final boolean postAtTime(Runnable r, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }
    
    //指定时间扔出一个Runnable,额外增加一个token
    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
    {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }
    
    //延时扔出一个Runnable
    public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
    
    //延时扔出一个Runnable,携带一个token;token会对应Message的obj属性
    public final boolean postDelayed(Runnable r, Object token, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r, token), delayMillis);
    }

    //这里是立即执行,正常我们普通的post只会仍在消息队尾,这个直接插队,执行时间为0(也就是立即执行)
    public final boolean postAtFrontOfQueue(Runnable r)
    {
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }

    //这里主要解决的是两个不同线程的handler的交互操作
    //如果在同一个Looper(线程相同),则立即执行
    //线程不同则构建一个BlockingRunnable,它是一个阻塞Runable;在它的run方法中执行了我们传入的runnable#run()方法;
    //但是在postAndWait方法中,如果没有超时则将当前线程陷入阻塞(wait),然后当我们的runnable#run方法执行时则会唤醒然后返回;
    //总结一下就是:在A线程提交的runable,将它提交到B线程,并等待runnable在B线程完成后才继续执行A线程的代码;
    public final boolean runWithScissors(final Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }

        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }

        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }

    //从消息队列中移除一个消息
    public final void removeCallbacks(Runnable r)
    {
        mQueue.removeMessages(this, r, null);
    }

    //从消息队列中移除一个消息,携带一个token;和前面的构建时传入token相呼应,token对应着Message的obj属性
    public final void removeCallbacks(Runnable r, Object token)
    {
        mQueue.removeMessages(this, r, token);
    }

    //发送一个消息
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

    //发送一个空消息
    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }

    //延时发送一个空消息
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

    //指定时间发送一个空消息
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }

    //延时发送一个消息
    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);
    }

    //立即执行的消息
    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        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, 0);
    }

    public final boolean executeOrSendMessage(Message msg) {
        //判断当前的经过赋值操作过的mLooper是否是依附于当前线程创建的Looper;主要用于判断是否经过了线程的切换,如果在同一线程,则直接分发执行消息;
        //Handler主要是异步消息分发调度使用,如果现在不是异步,就不需要经过一系列流程了,可以直接去执行了
        if (mLooper == Looper.myLooper()) {
            dispatchMessage(msg);
            return true;
        }
        //经过了线程的切换则发送消息到MessageQueue中
        return sendMessage(msg);
    }

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        //指定消息目标也就是Handler本身
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //将Message经过排序扔到MessageQueue中
        return queue.enqueueMessage(msg, uptimeMillis);
    }

    //根据标签what移除Message
    public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);
    }

    //移除Message
    public final void removeMessages(int what, Object object) {
        mQueue.removeMessages(this, what, object);
    }

    //移除消息和回调
    public final void removeCallbacksAndMessages(Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }

    //检查消息队列中是否已经加入该消息
    public final boolean hasMessages(int what) {
        return mQueue.hasMessages(this, what, null);
    }

    //检查消息队列中是否已经加入该消息或回调
    public final boolean hasMessagesOrCallbacks() {
        return mQueue.hasMessages(this);
    }

    //检查消息队列中是否已经加入该消息
    public final boolean hasMessages(int what, Object object) {
        return mQueue.hasMessages(this, what, object);
    }

    //检查消息队列中是否已经加入该回调
    public final boolean hasCallbacks(Runnable r) {
        return mQueue.hasMessages(this, r, null);
    }

    //获取Handler的Looper
    public final Looper getLooper() {
        return mLooper;
    }

    public final void dump(Printer pw, String prefix) {
        pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
        if (mLooper == null) {
            pw.println(prefix + "looper uninitialized");
        } else {
            mLooper.dump(pw, prefix + "  ");
        }
    }

    /**
     * @hide
     */
    public final void dumpMine(Printer pw, String prefix) {
        pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
        if (mLooper == null) {
            pw.println(prefix + "looper uninitialized");
        } else {
            mLooper.dump(pw, prefix + "  ", this);
        }
    }

    @Override
    public String toString() {
        return "Handler (" + getClass().getName() + ") {"
        + Integer.toHexString(System.identityHashCode(this))
        + "}";
    }

	//这个Messager目前用到的地方已知有Message.replyTo这个字段可以赋值;另外在Messager的send方法也是调用这里的send的方法(Messager构造入参为Handler);
	//当在onServiceConnected方法中拿到Binder来构建Message时,内部就是拿到远端的Handler代理,然后发消息给远端的Handler执行;
    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

    private static Message getPostMessage(Runnable r, Object token) {
        Message m = Message.obtain();
        m.obj = token;
        m.callback = r;
        return m;
    }

	//简单封装
    private static void handleCallback(Message message) {
        message.callback.run();
    }

    final Looper mLooper;
    final MessageQueue mQueue;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;
	
	//对应上面的runWithScissors,阻塞执行(在WMS中有使用到)
    private static final class BlockingRunnable implements Runnable {
        private final Runnable mTask;
        private boolean mDone;

        public BlockingRunnable(Runnable task) {
            mTask = task;
        }

        @Override
        public void run() {
            try {
                mTask.run();
            } finally {
                synchronized (this) {
                    mDone = true;
                    notifyAll();
                }
            }
        }

        public boolean postAndWait(Handler handler, long timeout) {
            if (!handler.post(this)) {
                return false;
            }

            synchronized (this) {
                if (timeout > 0) {
                    final long expirationTime = SystemClock.uptimeMillis() + timeout;
                    while (!mDone) {
                        long delay = expirationTime - SystemClock.uptimeMillis();
                        if (delay <= 0) {
                            return false; // timeout
                        }
                        try {
                        	//只要上面的run还没有执行 且 还没有超过指定超时时间则进入等待
                            wait(delay);
                        } catch (InterruptedException ex) {
                        }
                    }
                } else {
                    while (!mDone) {
                        try {
                        	//没有传入正确的超时时间则只要run没有有执行完就一直等待
                            wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            }
            //整个run执行完了才到这一步返回,相对发起者线程会一直阻塞
            return true;
        }
    }
}

以上代码已经逐行解释了一遍,当然还有一些不好解释的或者很少见到的就留到了下面来解释;不过因为已解释的代码足够走完流程,那就先走一下流程,按照使用方式

###1、普通回调


    public static final int MSG1 = 0x1002;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG1:
                    Object obj=msg.obj;
                    int arg1=msg.arg1;
                    int arg2=msg.arg2;
                    //update UI
                    
                    break;
                default:
                    break;
            }
        }
    };
    
    //发送消息
    Message message = Message.obtain();
    message.what =MSG1;
    message.obj=new Object();
    message.arg1=0;
    message.arg2=1;
    
    //发送消息
    handler.sendMessage(message);
    handler.sendEmptyMessage(MSG1);
    handler.sendMessageDelayed(message,0);
    handler.sendEmptyMessageDelayed(MSG1,0);
    handler.sendMessageAtTime(message,0);
    handler.sendEmptyMessageAtTime(MSG1,0);
    handler.sendMessageAtFrontOfQueue(message);

这种是比较常用的,看一下他的流程
使用了匿名无参的构造,并重写了handlerMessage方法;构造了一个Message,然后send了出去
一般是sendMessage,有时多个Delayed,这个是延时,无非就是延时多少时间后发送出去,Empty也好理解,发送一个空消息,不带参数,只用作通知使用;那AtTime是什么意思呢,这个是指定时间(这个时间是你的开机时间,假设你昨天开的机,到现在已经过去了24601000,假设是一天哈,如果你传入的时间小于这个数字则立刻执行,否则就是到了你输入的时间才执行;SystemClock.uptimeMillis()是当前开机时间)

先看看Handler的空构造

public Handler() {
    this(null, false);
}

调用了,Callback是

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 " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //关键代码
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

有的之前解释过了,这里主要是初始化Handler,顺带着获取到Looper和Message,同时Callback=null。
这里调用Looper.myLooper()来获取Looper;

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

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

public static void prepare() {
    prepare(true);
}

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

这里就是他的由来,ThreadLocal是用来存储线程共享变量的副本;
在这里sThreadLocal.get()就是直接获取存储的Looper对象,他是在prepare中存储的;那何时调用prepare呢,如果是在主线程中创建的handler,那就是在APP启动的时候(ActivityThread#main()中调用Looper.prepareMainLooper())会调用prepare;如果是在子线程中调用,则在Handler实例化之前需要先调用Looper.prepare()方法

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

上面的实例化代码可以看出,在构造函数里面初始化了MessageQueue和MThread,同时因为prepare中:

if (sThreadLocal.get() != null) {
    throw new RuntimeException("Only one Looper may be created per thread");
}

所以sThreadLocal中只有一个Looper对象,也就是说只有一个MessageQueue

到这里初步工作就做好了;

然后发送消息sendXXXMessageXXX

sendMessage(Message msg)
//连环调用1-1
public final boolean sendMessage(Message msg){
    return sendMessageDelayed(msg, 0);
}
//连环调用1-2
public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//连环调用1-3
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    //取得初始化获取到的MessageQueue对象
    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);
}
//连环调用1-4
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    //指定target为handler对象本身
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
//连环调用1-5 到了MessageQueue.class
boolean enqueueMessage(Message msg, long when) {
        //Handler不能为null
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        //判断这个Message是否正在使用,这说明了Message的唯一性
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        //锁住该MessageQueue对象
        synchronized (this) {
            //接收的线程是否挂了;比如主线程Handle发送一个消息到子线程中去处理,但是这时候子线程已经挂了,那这个消息也就作废了
            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();
                return false;
            }
            //消息设置为正在使用
            msg.markInUse();
            //赋值消息执行的时间
            msg.when = when;
            //mMessage为即将要处理的消息(可以理解为消息头)
            Message p = mMessages;
            boolean needWake;
            //如果MessageQueue中没有消息了或者传进来的消息将要执行的时间比即将要处理的消息要近则将mMessage指向传进来的Message对象
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                //否则按照消息队列中的执行时间进行排序
                //如果当前处于阻塞等待状态 并且消息头是屏障消息 并且当前消息是异步消息;(则当前阻塞住了同步消息,正在执行异步消息)
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    //消息遍历,找到自己时间戳所处的位置
                    if (p == null || when < p.when) {
                        break;
                    }
                    //如果当前正处于执行异步消息,而当前消息就是异步消息则不需要唤醒;
                    //能执行到这一步,就说明p不是null,也就不是一直阻塞,而是相对于第一个消息的延迟时间而阻塞的,就把不需要唤醒;
                    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;
    }

上面的needWake首先为true的条件是:

needWake = mBlocked && p.target == null && msg.isAsynchronous();

也就是:如果当前处于阻塞等待状态 并且消息头是屏障消息 并且当前消息是异步消息;(则当前阻塞住了同步消息,正在执行异步消息)

下面还有个:

if (needWake && p.isAsynchronous()) {
	needWake = false;
}

该代码是p不为null的else分支里面,所以当前处于同步屏障时刻,只要没移除同步屏障就一直在这卡着只走异步消息;而异步消息也分立即执行和延迟执行;
走到for循环里面看:

  • 如果下一个消息是null,也就是当前没有消息了,也就没有异步消息了,则说明之前是一直阻塞着,于是直接唤醒执行;
  • 如果找到了对应的位置(时间戳排序,位置不区分同步异步,只区分时间),因为当前是异步消息,于是也需要唤醒,因为存在两种情况:
    • 当前消息队列直接没有异步消息了在阻塞中,此时需要唤醒
    • 当先消息队列有异步消息,可能是延时3秒后执行,于是阻塞也是3秒;但是当前消息的时间可能在这个异步消息前面,则需要唤醒重新按照短的时间来阻塞
  • 如果同步屏障后的第一个消息就是异步消息且时间位置在当前消息前面,则说明当前的阻塞就是在阻塞第一个异步消息的延时,所以不需要唤醒,时间到了会自动唤醒。
sendEmptyMessage
//连环调用2-1
public final boolean sendEmptyMessage(int what){
    return sendEmptyMessageDelayed(what, 0);
}
//连环调用2-2
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}
//连环调用2-3
public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//连环调用2-4
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);
}
//连环调用2-5 殊途同归,最终到MessageQueue的enqueueMessage
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

这俩唯一的区别就是一个是需要自己构建Message,指定携带参数,而EmptyMessage只是内初获取一个Message,然后指定一个what参数

####sendMessageAtFrontOfQueue

//连环调用3-1
public final boolean sendMessageAtFrontOfQueue(Message msg) {
    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, 0);
}
//连环调用3-2
public final boolean sendMessageAtFrontOfQueue(Message msg) {
    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, 0);
}

又是殊途同归,他的区别就是在开机后的第0秒就开始执行,也就是发出即执行,作用等同于sendMessage
还记得MessageQueue中的enqueueMessage中的:

if (p == null || when == 0 || when < p.when) {
    ...
}

这里的when==0就是这种情况,至于开机的一瞬间发送sendMessage达到when=0那就是…

到了这时候Handler已经初始化了,消息也发送到了MessageQueue中,还差什么?差执行啊,怎么执行?既然是个MessageQueue,那就是排队执行了,Looper.loop就达到了这个作用

public static void loop() {
        //获取当前Looper所在线程中的Looper对象
        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();

        // 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
            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;
            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
            if (thresholdOverride > 0) {
                slowDispatchThresholdMs = thresholdOverride;
                slowDeliveryThresholdMs = thresholdOverride;
            }
            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
            final boolean needEndTime = logSlowDispatch;

            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            try {
                //开始分发事件进行处理:target是Handler对象本身,所以回调Handler的dispatchMessage方法
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (logSlowDelivery) {
                if (slowDeliveryDetected) {
                    if ((dispatchStart - msg.when) <= 10) {
                        Slog.w(TAG, "Drained");
                        slowDeliveryDetected = false;
                    }
                } else {
                    if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                            msg)) {
                        // Once we write a slow delivery log, suppress until the queue drains.
                        slowDeliveryDetected = true;
                    }
                }
            }
            if (logSlowDispatch) {
                showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", 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();
        }
    }

上面的代码是在MessageQueue中死循环取出Message进行分发到了Handler的dispatchMessage,这个方法我们一开始就分析过,这里再拿出来看看

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

我们实例化Handler的时候

public Handler() {
        this(null, false);
    }

mCallback是等于null的,而msg.callback是在post的时候才会非空,所以回调了handleMessage(msg);这是个空实现,也就是我们来处理回调信息,一般是更新UI;


这里来看一下post的使用方式

new Handler().post(new Runnable() {
    @Override
    public void run() {

    }
});
//连环调用1-1
public final boolean post(Runnable r){
    return  sendMessageDelayed(getPostMessage(r), 0);
}
//获取一个Message,同时将Runnable赋值给message的callback
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}
//连环调用1-2
public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//殊途同归

后面都一样,这里只是将传入的runnable包装成Message,最终回调Runnable它本身的run方法;
在这

public void dispatchMessage(Message msg) {
    //这呢
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
private static void handleCallback(Message message) {
    message.callback.run();
}

这里Handler常规的使用涉及到的源码都分析了一遍,不知道有没有注意到一个东西
mAsynchronous:标记为异步
这个东西标记Message为异步,也就是MessageQueue中的消息并不都是串行执行的,还可能有异步消息;
有setAsynchronous那就肯定有isAsynchronous,看了一下他的引用是在MessageQueue中的Message next() {…}中,另一处就是MessageQueue中的enqueueMessage(Message msg, long when),这两个方法我们都见过,next目前还没详细了解过,只知道他是指向下一个Message,但是enqueueMessage(Message msg, long when)我们熟啊,Handler发送消息的最终调用不就是这个吗?

if (p == null || when == 0 || when < p.when) {
    msg.next = p;
    mMessages = msg;
    needWake = mBlocked;
} else {
    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;
}

当初这一块的逻辑我们是概括性的讲了一下,如果MessageQueue中有消息那就按照执行事件去排个序,现在看来不止排序这么简单啊,里面竟然还搞事情了;那就逐步分析

boolean enqueueMessage(Message msg, long when) {
        //就是在他的上一步指定的Handler
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        //消息是否已经在使用
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
        //锁定MessageQueue对象
        synchronized (this) {
            //Handler要分发到的处理线程如果挂了,那这个消息到此为止
            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();
                return false;
            }
            //设置标签:消息在使用
            msg.markInUse();
            //赋值将要处理消息的时间
            msg.when = when;
            //获取将要执行的消息对象,mMessages指代将要执行的消息对象
            Message p = mMessages;
            //判断是否需要执行
            boolean needWake;
            //p==null:消息队列空了
            //when==0:这个之前解释过,一般是调用了sendMessageAtFrontOfQueue方法,等同于立即执行
            //when < p.when:消息执行的时间小于将要执行的消息的时间
            if (p == null || when == 0 || when < p.when) {
                //这是将消息指向mMessage作为将要执行的消息,同时它的下一个执行消息仍然指向了mMessage
                msg.next = p;
                mMessages = msg;
                //如果当前是阻塞的,因为该消息处于第一个则需要唤醒
                needWake = mBlocked;
            } else {
                //队列中不为空而且执行时间并不是最近的就else了
                //不需要调整唤醒时间(有一个最近唤醒时间)
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                //自循
                for (;;) {
                    //指向下一个即将执行的Message
                    prev = p;
                    //再往下走一步
                    p = p.next;
                    //如果走到头了或者时间在某个Message执行时间前面则结束掉自循
                    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;
    }

也就是说如果当前插入的是异步消息,且碰上了同步屏障开启了;如果当前阻塞了,则直接根据位置和时间点来判断是否唤醒。


再来说说第二个问题,handler既然是做异步调度的,那他是何时从子线程调度到主线程或者他是何时从主线程调度到子线程的?
我们按照调用思路来,他是依附于Looper指定的线程创建的,如果是主线程中创建的Handler,那就指定了主线程中,那他的MessageQueue也是在主线程中,那最终的回调就在主线程中;这里你可能会有疑问,handler不是在子线程中发的消息吗?是的,消息是从子线程中发出来的,但此时他认准的是主线程的MessageQueue,在子线程中向主线程中的MessageQueue中扔消息可以吗?可以的;
就比如说,我往路上扔了一根针,有人捡到了,然后做成了鱼钩,疯狂钓鱼影响了生态平衡,但是你能说这生态平衡是我引发的吗?不能,我只是扔了一根针,再回过来,handler在子线程中发了一条消息,然后别人根据这个消息更新了UI,你能说是在子线程中更新了UI吗?也不能,handler只是发送了一条消息。


4.1.2说说“同步分割栏”


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值