Handler消息机制源码分析

作为一个Android开发人员,或者对Android由一定了解的人员,我想你对于Handler并不陌生,作为Android中最基础的组件之一,几乎所有的Android面试都会有关于Handler消息机制的题目,所以对于作为Android开发人员的我们,有什么理由不去了解Android的底层原理呢?
在Android的Handler消息机制中,主要有Handler,Message、MessageQueue、Looper

Handler

在Handler消息几种中,Handler类的作用主要是负责发送消息和最终对消息的处理,Handler的构造方法有六个构造方法,有三个参数,这三个参数为(@NonNull Looper looper, @NonNull Callback callback, boolean async),由注解可知looper和callback传入是不能为空,而当不传入looper对象时,构造方法也会去通过Looper静态方法获取looper对象,而当获取的looper对象为空时,程序会抛出异常,提示必须先调用Looper.prepare()方法,Looper.prepare()方法会创建一个looper对象,然后和当前线程绑定,具体如何实现请看Looper部分讲解。callback参数则是handler事件处理回调函数,传入这个参数后就可以不用实现handler子类来处理回调事件了。async参数为true则表示当前handler对象是否为异步handler,客户端一般不使用handler发送异步消息,所以一般来说我们都不使用带这个参数的构造方法,而且带有该参数的构造方法都是@hide方法,所以需要创建异步handler需要通过Handler的静态方法createAsync。至于同步消息和异步消息有什么区别,请看Looper部分

public Handler(@Nullable 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();//获取looper对象
	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通过postXX或者sendXX发送消息,源码如下

    public final boolean post(@NonNull Runnable r) {//任务调度
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {//定时执行任务
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }
    public final boolean postAtTime(//带有验证信息的定时任务
            @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
    }
    public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {//延时任务调度
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
    public final boolean postDelayed(Runnable r, int what, long delayMillis) {//带有额外信息what的延时任务调度
        return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
    }
    public final boolean postDelayed(//带有验证信息的延时任务调度
            @NonNull Runnable r, @Nullable Object token, long delayMillis) {
        return sendMessageDelayed(getPostMessage(r, token), delayMillis);
    }
    public final boolean postAtFrontOfQueue(@NonNull Runnable r) {//优先执行的任务调度
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }
    public final boolean sendMessage(@NonNull Message msg) {//发送一个msg信息
        return sendMessageDelayed(msg, 0);
    }
    public final boolean sendEmptyMessage(int what) {//发送一个空的msg信息
        return sendEmptyMessageDelayed(what, 0);
    }
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {//发送一个空的且延时的msg信息
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {//发送一个空的且定时的msg信息
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }
    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {//发送一个延时的msg信息
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {//发送一个定时的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, uptimeMillis);//消息入队
    }
    public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
        MessageQueue queue = mQueue;
        if (queue == null) {//消息队列为空时抛出异常,在Looper.prepare()中创建,创建looper对象后就不会为空
            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(@NonNull Message msg) {
        if (mLooper == Looper.myLooper()) {//如果时同一线程,则直接执行,否则入队
            dispatchMessage(msg);
            return true;
        }
        return sendMessage(msg);
    }
    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();
        if (mAsynchronous) {//如果时异步消息,则先标记message为异步消息
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);//通过消息队列进行入队
    }

通过上面方法我们可以知道无论通过sendXX发送消息还是通过postXX调度任务,最终都需要通过MessageQueue的enqueueMessage方法进入队列,不同之处仅在于任务内容和处理任务时间不同,以及是否为异步消息。最后通过Looper进行消息队列的处理,最后通过handler的dispatchMessage方法经行分发,分发代码如下

public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {//callback对象为Runnable,不为空的是直接运行runnable方法
            handleCallback(msg);
        } else {
            if (mCallback != null) {//mCallback是构造handler时传入的callback,不为空的话通过它分发消息
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);//msg和handler的callback都为空时需要,创建handler时需要实现该方法进行任务的分发处理
        }
    }

此外Messenger主要通过Handler的getIMessenger方法来实现进程间的通信

Looper

在一个线程中需要使用handler消息机制需要先通过Looper.prepare()创建looper对象,而且有源码可知,prepare方法只能被一个线程调用一次,looper对象通过静态常量对象sThreadLocal和线程进行绑定,从而确保了每个线程都只有一个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));
}

looper核心的方法是loop方法,loop方法里面是一个是循环,在这个死循环里主要负责维护MessageQueue队列的出队并且保证线程持续的运行,然后对出队消息进行分发。
在面试过程中往往会遇到这么一个问题,为什么loop方法不会导致ANR呢?解决这个额问题我们先得清楚ANR出现的条件,第一种情况是在Service的生命周期和BroadcastReceiver的onReceiver方法中执行耗时操作;第二种是在输入事件在5s内没有完成且有下一个事件等待处理的情况下。而loop的死循环会及时把收到的消息分发个各个handler对象处理,所以ANR和死循环并没有直接关系,而ANR只是主线程维护的死循环中一部分代码执行超时的结果。如果没有了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;//获取消息队列

    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    final int thresholdOverride =
            SystemProperties.getInt("log.looper."
                    + Process.myUid() + "."
                    + Thread.currentThread().getName()
                    + ".slow", 0);

    boolean slowDeliveryDetected = false;

    for (;;) {
        Message msg = queue.next(); //获取下一个待处理的消息,如果没有消息,线程会阻塞在这里
        if (msg == null) {//如果消息为空的会推出循环,可通过quit和quitSafely方法清空消息队列
            return;
        }

        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }
        final Observer observer = sObserver;//消息队列处理监听器,设置接口为hide接口

        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;
        Object token = null;
        if (observer != null) {
            token = observer.messageDispatchStarting();
        }
        long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
        try {
            msg.target.dispatchMessage(msg);//消息分发
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } catch (Exception exception) {
            if (observer != null) {
                observer.dispatchingThrewException(token, msg, exception);
            }
            throw exception;
        } finally {
            ThreadLocalWorkSource.restore(origWorkSource);
            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)) {
                    slowDeliveryDetected = true;
                }
            }
        }
        if (logSlowDispatch) {
            showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
        }

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        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资源,并根据使用情况存入到sPool
    }
}

loop方法中除了读messageQueue队列之外还做了一些日志,监听器,以及多进程通信的一些处理,但是主要逻辑还是消息的读取和分发

Message

Message是MessageQueue的节点对象,不仅封装what、arg1、arg2、obj及data等数据对象,还封装了next节点对象,所以MessageQueue队列是链表的数据结构,它还实现了Parcelable序列化,在进程Messager进程通信时也是通过其实现数据的传递。此外message还采用了GOF设计模式中的享元模式,我们可以通过Message的obtain方法创建message对象,这样可以减少对象的创建而达到内存优化的效果,Handler对象中的obtainMessage也是调用了Message中的obtain方法。

MessageQueue

上面我们已经提到过了,handler的sendXX或者postXX方法最终都会调用handler的enqueueMessage方法,而其最终调用的也是messageQueue的enqueueMessage方法。此方法会将msg消息按照when的先后顺序入队

boolean enqueueMessage(Message msg, long when) {
    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.");
    }

    synchronized (this) {
        if (mQuitting) {//调用quit方法后,不在处理任何消息
            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;
        Message p = mMessages;
        boolean needWake;
        if (p == null//第一次发送handler消息前为空
         || when == 0//通过handler的sendMessageAtFrontOfQueue方法发送时when为0
          || when < p.when) {//消息的处理时间小于当前处理的消息时间时直接将msg
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;//mIdleHandlers没有元素时为true
        } else {
            needWake = mBlocked && p.target == null && msg.isAsynchronous();//如果插入一个屏障消息
            Message prev;
            for (;;) {//遍历队列中的节点信息,并根据设定的when的大小将msg插入到合适的位置
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p;
            prev.next = msg;
        }

        if (needWake) {
            nativeWake(mPtr);//在没有消息的时候线程会通过nativePollOnce方法进行休眠
            //此方法可以唤醒线程休眠状态
        }
    }
    return true;
}

消息出队

Message next() {
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount = -1;
    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }

        nativePollOnce(ptr, nextPollTimeoutMillis);//在没有消息的时候会阻塞,当有消息时会被及时唤醒

        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) {//如果当前消息是一个屏障消息,则优先处理异步消息,没有异步效益时,msg被赋值为null
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                if (now < msg.when) {//如果是一条延时消息,则计算延时时长
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {//移除当前节点
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                    msg.markInUse();
                    return msg;
                }
            } else {
                nextPollTimeoutMillis = -1;
            }

            if (mQuitting) {
                dispose();
                return null;
            }

            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                mBlocked = true;
                continue;
            }

            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        }

        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            mPendingIdleHandlers[i] = null; 

            boolean keep = false;
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }

            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }

        pendingIdleHandlerCount = 0;
        nextPollTimeoutMillis = 0;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值