大多数状况下,handleMessage
所在线程和 handler 初始化所在的线程相同,但 handler 初始化的时候能够传入一个 Looper 对象,此时handleMessage
所在线程和参数looper
所在线程相同。java
public Handler(Looper looper)
class MainActivity : AppCompatActivity() { var handler: Handler? = null var looper: Looper? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) looper = Looper.getMainLooper() val thread = object : Thread() { override fun run() { super.run() Log.e("abc", "--- Runnable:threadName ---" + Thread.currentThread().name) handler = object : Handler(looper) { override fun handleMessage(msg: Message?) { super.handleMessage(msg) Log.e("abc","--- handleMessage:threadName ---" + Thread.currentThread().name ) } } } } thread.start() myBtn.setOnClickListener { val msg = Message() handler!!.sendMessage(msg) } } } // log 打印状况 --- Runnable:threadName ---Thread-2 --- handleMessage:threadName ---main
从 log 中能够看到 handler 初始化所在线程在 Thread-2,而handleMessage
所在的线程是主线程main
.ide
若是使用无参的 Handler 初始化构造,须要手动调用Looper.prepare()
和Looper.loop()
:oop
val thread = object : Thread() { override fun run() { super.run() Log.e("abc", "--- Runnable:threadName ---" + Thread.currentThread().name) Looper.prepare() handler = object : Handler() { override fun handleMessage(msg: Message?) { super.handleMessage(msg) Log.e( "abc", "--- handleMessage:threadName ---" + Thread.currentThread().name ) } } Looper.loop() } } // log 打印状况 --- Runnable:threadName ---Thread-2 --- handleMessage:threadName ---Thread-2
不手动调用Looper.prepare()
会抛出异常:post
java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-2,5,main] that has not called Looper.prepare()
主线程中使用 Handler:
大多数时候咱们不会在子线程中初始化和使用 handler,而是在主线程中使用,此时不须要prepare()
和loop()
,由于主线程中自带一个 Looper(经过Looper.getMainLooper()
能够获取)
查看Looper.prepare()
源码:ui
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)); }
继续查看sThreadLocal.set(new Looper(quitAllowed))
:this
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
Threadlocal 是一个线程内部的存储类,能够在指定线程内存储数据,数据存储之后,只有指定线程能够获得存储数据。在这里 ThreadLocal 的做用是保证了每一个线程都有各自的 Looper,就是说 一个线程只能有一个 Looper,关于 Threadlocal,能够看看这篇文章 Threadlocal
接下来看看建立 Looper 实例的方法new Looper(quitAllowed)
:线程
final MessageQueue mQueue; final Thread mThread; private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();
在构造方法里,初始化 了MessageQueue 和表明当前线程的属性 mThread.code
调用
Looper.prepare()
其实就是利用 ThreadLocal 为当前的线程建立了一个独立的 Looper,这其中包含了一个消息队列
一个线程只能有一个 Looper,但一个线程中能够建立多个 Handler,那么一个 Looper 怎么和多个 Handler 对应呢?查看源码可知,post(Runnable r)
、postDelayed(Runnable r, long delayMillis)
、postAtTime(Runnable r, long uptimeMillis)
和sendMessage
最终调用的都是enqueueMessage
方法:对象
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
msg.target = this
这里就是将当前的 Handler 赋值给 Message 对象的 target 属性,这样在处理消息的时候经过msg.target
就能够区分开不一样的 Handler 了。队列