Handler的内部机制原理

图解Handle

Handler内部通信机制原理图解
Handler内部通信机制的实现
1、Looper是每个线程独有的,通过loop()方法读取下面的MessageQueue,读到消息后发送给Handler进行处理。
2、MessagQueue是消息队列,是先进先出的方式管理Message的。
3、创建Looper的时候就已经创建了MessageQueue,所以说创建Looper的时候就已经和MessageQueue关联到一起了。
4、Message就是消息对象,里边存有很多参数如上图。
5、Handler有两个作用:发送消息,处理消息;Handler发送消息不能漫无目的的发送,只能发送给他相关的线程。Handler发送消息必须 有一个维系他的Looper

源码对Handler的消息进行解析

Handler构造
1、深入到Looper的的获取

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

2、通过ThreadLocal的get()方法获取 ,ThreadLocal的作用是通过不同的线程访问同一个ThreadLocal不管是它的set()方法还是get()方法他们对ThreadLocal做的读写操作仅限于各自线程内部,使每一个线程有单独的Looper。
调用Looper的方法
3、上图的方法中的prepare(false)方法是创建了Looper的
在这里插入图片描述
4、将Looper对象设置给了ThreadLocal,这样就保证了线程的唯一性,此方法是初始化Looper的。这个时候可以说整个MessageQueue通过Looper与线程关联上了。这样我们就可以在不同的线程访问不同的消息队列
5、回到Handler的构造函数中去,由于在构造中我们已经创建了Looper,又通过Looper创建了MessageQueue,此时Handler已经和MessageQueue关联到一起了,MessageQueue又是通过Looper来进行管理的。
6、我们在使用Handler时,为了保证Handler更新UI是在主线程时,一定要在主线程中创建Handler,而不能在内部类中创建Handler,这样才能让Handler中的HandMessage运行在主线程中,这样才能保证UI线程是线程安全的

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

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

7、此代码为Looper的Loop()方法,我们可以清楚的看见他是创建了一个死循环,然后从消息对列中逐个获取消息然后处理消息的过程
8、对于Looper我们可以总结一下,首先,通过Prepare方法创建Looper,然后将Looper保存待本地的ThreadLocal中然后通过Looper.loop()开启循环来进行消息的分发
9、我们在loop方法中可以发现有一个dispatchMeesage()方法他的参数为taget,那我们可以发现,这个taget实际上就是一个Handler,也就是说通过Handler将消息放到消息对列中,而消息对列有分发给了Handler进行消息处理在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值