题目:Handler怎么进行线程通信,原理是什么?
首先我们要知道这道题想考察什么?
- 是否熟悉Handler的基本用法
- 是否熟悉Handler消息机制的运行流程
- 是否明白Handler进行线程通信的原理
考察的知识点
- 利用Handler进行线程切换的基本流程
- Handler消息机制涉及到的类以及之间的关系
- Handler是怎样做到线程通信的
考生应该如何回答
-
先说一下Handler机制的运行流程,以及涉及到的类之间的关系
Handler消息机制主要涉及到四个类:Handler、Looper、MessageQueue、Message.
Handler: 字面意为处理器,负责消息的分发与处理,内部持有一个looper对象和一个MessageQueue对象(MessageQueue对象通过looper对象获得)
Looper: 字面意为循环器,跑在特定的线程里面,持有一个MessageQueue对象,主要通过loop()方法循环地从MessageQueue中来拿到当前线程需要处理的消息并处理。我们通常意义上的切换线程,归根结底就是切换到了这个方法中。为什么需要loop()循环?通常我们开启一个新的线程,当代码执行完线程也就结束了,如果想要该线程做到不断接收并处理外部发来的消息,就需要开启looper。
MessageQueue: 消息队列,也就是存放Message的地方,维护了一个通过时间优先级排列的单链表,Handler发出的消息会先存进此队列再被取出执行。
Message: 消息,可携带参数及标识,并持有发送该消息的Handler对象。post(Runnable)方式最后也会被改为Message对象,并将Runnable赋值给Message的callback,处理消息时调用。
一次完整的事件发送与处理流程为:Handler调用sendMessage/post方法,调用其持有的MessageQueue对象的enqueueMessage方法将消息添加到消息队列,looper通过loop()方法会不断的从该MessageQueue中取出Message,并调用Message持有的target(Handler)对象的dispatchMessage方法,进而执行到Handler的handlerMessage或者Runnable的run方法或者额外的callback进行处理。
-
说一下Handler怎么做到线程通信,其原理是什么
我们在新建一个Handler的时候,在其构造方法中会给其持有的mLooper对象赋值,Handler通过mLooper实现与线程的绑定。
mLooper对象可以在构造方法中传入,或者在构造方法中通过Looper.myLooper()方法获取。
//Handler.java public Handler(@Nullable Callback callback, boolean async) { mLooper = Looper.myLooper(); mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } //Looper.java static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); public static @Nullable Looper myLooper() { return sThreadLocal.get(); } private static void prepare(