摘要:在中查看源码在看源码时会发现来自于,下面来看的源码在构造函数中创建了并且将当前线程和关联起来。那么如何创建对象呢在的构造函数中默认的是通过获得的,我们来看看这个方法。
在Android-27中查看源码
在看Handler源码时会发现MessageQueue来自于Looper,下面来看Looper的源码:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
在构造函数中创建了MessageQueue并且将当前线程和Looper关联起来。但该方法是私有的,无法直接new对象。那么如何创建对象呢?在Handler的构造函数中默认的Looper是通过Looper.myLooper()获得的,我们来看看这个方法。
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
该方法返回和当前线程相关联的Looper,如果当前线程没有关联的Looper则返回null。
如何将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.prepare()方法中创建了Looper对象并保存在ThreadLocal中,在使用时通过Looper.myLooper()将保存的Looper取出来。关于ThreadLocal可以参考文章ThreadLocal源码
接下来,我们看到了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 slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (slowDispatchThresholdMs > 0) { final long time = end - start; if (time > slowDispatchThresholdMs) { Slog.w(TAG, "Dispatch took " + time + "ms on " + Thread.currentThread().getName() + ", h=" + msg.target + " cb=" + msg.callback + " msg=" + msg.what); } } 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(); } }
在loop方法中存在一个无限循环,不断从消息队列中取出消息,然后交给msg.target(即Handler)去调用dispatchMessage处理取出的消息。只有在消息队列为空的时候才跳出循环。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/14527.html
摘要:在子线程中发送消息,主线程接受到消息并且处理逻辑。也称之为消息队列,特点是先进先出,底层实现是单链表数据结构得出结论方法初始话了一个对象并关联在一个对象,并且一个线程中只有一个对象,只有一个对象。 目录介绍 1.Handler的常见的使用方式 2.如何在子线程中定义Handler 3.主线程如何自动调用Looper.prepare() 4.Looper.prepare()方法源码分析...
摘要:在中可以通过来更新主线程中的变化,更新只能在主线程中进行更新,而为了让其他线程也能控制的变化,提供了一种机制与一同协作来达到其他线程更新的目的。这样一来就通过联系上了所绑定的线程,即为主线程。 在Android中可以通过Handler来更新主线程中UI的变化,更新UI只能在主线程中进行更新,而为了让其他线程也能控制UI的变化,Android提供了一种机制Handler、Looper与M...
摘要:一概述先来了解一下的几个特性继续于本身就是一个线程类在内部维护了自己的对象,所以可以进行循环创建后需要先调用方法再向其下发任务,通过方法来创建对象通过传递的对象给对象,从而可以通过来向下发号是任务二使用方式再来看的使用方式创建并调用方法,使 一、概述 先来了解一下HandlerThread的几个特性 HandlerThread继续于Thread,本身就是一个线程类 HandlerTh...
摘要:比如处理用户交互的线程,它等待并执行用户的点击滑动等等操作事件,也执行由系统触发的广播等事件,称之为主线程,也叫线程。源码链接源码链接源码链接源码链接版权声明消息处理机制总结笔记由在年月日写作。 一次性线程和无限循环线程 普通线程是一次性的,执行结束后也就退出了(这种说法可能不严谨,但为了下文描述方便)。但某些情况下需要无限循环、不退出的线程。比如处理用户交互的线程,它等待并执行用户的...
摘要:在分析之前,先要了解。对象可用于创建类。这些在上一篇文章中已经分析过。处理完成后会调用自动停止。为了把它执行的结果体现在上,需要把结果返回给。正在执行的任务无法打断。 简介 Service 是 Android 四大组件之一,用于后台运行,但由于 Service 依然运行在主线程,所以是不能直接进行耗时操作的。如果有耗时操作,还是需要放到子线程中,可以手动开启线程,也可以使用 Andro...
阅读 2985·2021-11-10 11:36
阅读 2935·2021-11-02 14:39
阅读 2735·2021-10-08 10:05
阅读 1495·2021-09-26 10:11
阅读 4294·2021-09-22 15:57
阅读 1444·2021-09-09 11:36
阅读 1890·2019-08-30 12:56
阅读 3344·2019-08-30 11:17